My application is using MEF to export some classes from an external assembly. These classes are setup for constructor injection. The issue I am facing is that MEF is attempting to instantiate the classes when I try to access them. Is there a way to have Ninject take care of the instantiation of the class?
IEnumerable<Lazy<IMyInterface>> controllers =
mefContainer.GetExports<IMyInterface>();
// The following line throws an error because MEF is
// trying to instantiate a class that requires 5 parameters
IMyInterface firstClass = controllers.First().Value;
There are multiple classes that implement IMyInterface
and I would like to select the one that has a specific name and then have Ninject create an instance of it. I'm not really sure if I want laziness.
[Export(typeof(IMyInterface))]
public class MyClassOne : IMyInterface {
private MyRepository one;
private YourRepository two;
public MyClassTwo(MyRepository repoOne, YourRepository repoTwo) {
one = repoOne;
two = repoTwo;
}
}
[Export(typeof(IMyInterface))]
public class MyClassTwo : IMyInterface {
private MyRepository one;
private YourRepository two;
public MyClassTwo(MyRepository repoOne, YourRepository repoTwo) {
one = repoOne;
two = repoTwo;
}
}
Using MEF, I would like to get either MyClassOne
or MyClassTwo
and then have Ninject provide an instance of MyRepository
and YourRepository
(Note, these two are bound in a Ninject module in the main assembly and not the assembly they are in)
You could use the Ninject Load
mechanism to get the exported classes into the mix, and the you either:
kernel.GetAll<IMyInterface>()
The creation is lazy (i.e., each impl of IMyInterface
is created on the fly as you iterate over the above) IIRC, but have a look at the tests in the source (which is very clean and readable, you have no excuse :P) to be sure.
If you dont need the laziness, use LINQ's ToArray
or ToList
to get a IMyInterface[]
or List<IMyInterface>
or you can use the low-level Resolve()
family of methods (again, have a look in the tests for samples) to get the eligible services [if you wanted to do some filtering or something other than just using an instance - though binding metadata is probably the solution there]
Finally, if you can edit in an explanation of whether you need laziness per se or are doing it to illustrate a point. (and have a search for Lazy<T>
here and in general wrt both Ninject and autofac for some samples - cant recall if there are any examples in the source - think not as it's still on 3.5)
EDIT: In that case, you want a bind that has:
Bind<X>().To<>().In...().Named( "x" );
in the registrations in your modules in the child assembly.
Then when you're resolving in the parent assembly, you use the Kernel.Get<>
overload that takes a name
parameter to indicate the one you want (no need for laziness, arrays or IEnumerable
). The Named
mechanism is a specific (just one or two helper extensions implement it in terms of the generalised concept) application of the binding metadata concept in Ninject - there's plenty room to customise it if somethng beyond a simple name is insufficient.
If you're using MEF to construct the objects, you could use the Kernel.Inject()
mechanism to inject properties. The problem is that either MEF or Ninject
- has to find the types (Ninject: generally via Bind()
in Module
s or via scanning extensions, after which one can do a Resolve
to subset the bindings before instantiation - though this isnt something you normally do)
- has to instantiate the types (Ninject: typically via a Kernel.Get()
, but if you discovered the types via e.g. MEF, you might use the Kernel.Get(Type)
overloads )
- has to inject the types (Ninject: typically via a Kernel.Inject()
, or implicit in the `Kernel.Get())
What's not clear to me yet is why you feel you need to mix and mangle the two - ultimately sharing duties during construction and constructor injection is not a core use case for either lib, even if they're both quite composable libraries. Do you have a constraint, or do you have critical benefits on both sides?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With