Ninject Conventions with multiple Froms

285 views Asked by At

I have some code in a NinjectModule that sets up Mock bindings for all interfaces in multiple assemblies. Ninject 2 allowed me to call the From() methods multiple times inside the Scan lambda:

Kernel.Scan(scanner =>
{
    string first = "MyAssembly";
    Assembly second = Assembly.Load("MyAssembly");
    scanner.From(first);
    scanner.From(second);
    scanner.BindWith<MockBindingGenerator>();
});

The new way in Ninject 3 doesn't allow chained From() calls, as far as I can tell. This is the best equivalent I could come up with:

string first = "MyAssembly";
Assembly second = Assembly.Load("MyAssembly");

Kernel.Bind(x => x
    .From(first)
    .SelectAllInterfaces()
    .BindWith<MockBindingGenerator>());

Kernel.Bind(x => x
    .From(second)
    .SelectAllInterfaces()
    .BindWith<MockBindingGenerator>());

My new code breaks* when a single assembly is loaded multiple times, as seen above. Note that the first and second variables are of different types, so I can't simply combine them into a single call. My real production code has the same issue, but of course I'm not simply hard-coding the same assembly name twice.

So, how can I rewrite the above so that I can combine multiple From() calls and only call BindWith<> once?

Edit

* The binding code itself executes just fine. The exception occurs when I try to get an instance of an interface that exists in an assembly that was bound twice.

2

There are 2 answers

0
Ruben Bartelink On

Did you see the Join syntax at the bottom of https://github.com/ninject/ninject.extensions.conventions/wiki/Overview ? I imagine it's what you're after...

(For bonus points: If you saw the docs and it just didn't jump out, can you suggest whether you reckon it'd best be separated into a new Wiki page or do you have other ideas? If you're just consuming it from IntelliSense, can you suggest a way you might have discovered it more easily?

EDIT: On reflection, I'm guessing you didn't see it due to the fact that the .Join doesn't become available until you've done the .Select... bit. (BTW my interest in this is driven by the fact that I did some editing in the wiki; feel free to edit in anything you've learned from this encounter in there too.))

0
MikeWyatt On

I solved my problem by creating a list of all assembly names:

string first = "MyAssembly";                    // .From("MyAssembly")
Assembly second = Assembly.Load("MyAssembly");  // .From(Assembly.Load("MyAssembly"))
Type third = typeof(Foo);                       // .FromAssemblyContaining<Foo>

Kernel.Bind(x => x
    .From(new [] { first, second.FullName, third.Assembly.FullName })
    .SelectAllInterfaces()
    .BindWith<MockBindingGenerator>());