Breaking the .NET MEF import chain
For this example you can assume toplevel is importing ClassA. MEF seems to work great as long as you import everything (ie ClassX). Often you don't need to import because classB is in same namespace/file. As a result the import chain is now broken and myLog import is never composed. In my example ClassB is trying to import a Logger Service, which is something almost all classes might desire.
Which if any is the intended/best MEF solution to this issue?
1) Once import chain is broken never use import again. Instead you must start creating/passing all types to constructor (ie. new ClassB(myLog)). This works in this example but it is messy if there is intermediate classes in the chain not using the argument.
2) Make use of the IServiceLocator in the System namespace to import ClassB. As far as I know ServiceLocator (eg. Prism Framework) exist only to abstract the Dependency Injection scheme. For this example if ClassB could import the IServiceLocator then it could have imported ILogger.
3) Back at the toplevel call ComposeParts(ClassB). To prevent the toplevel from depending on ClassB I could have classB implement an Interface (IComposeMe), which the toplevel imports. Then the toplevel would ComposeParts on the container for all IComposeMe imports. I do not believe this is the intended solution, bec开发者_JS百科ause it is not described or used in the MEF framework documentation.
4) Actually I am out of ideas, please help...
class ClassA {
// Imports within ClassX will get composed
[Import]
ClassX myClassX;
// Imports within ClassB will NOT be composed!
var myClassB = new ClassB
}
class ClassB {
// Fails because ClassB is never Composed
[Import]
ILogger myLog;
myLog.Display("Hello World");
}
[Export]
class ClassX {
// Works - Imports are satified when ClassX imported
[Import]
ILogger myLog;
myLog.Display("Hello World");
}
The preferred approach if you follow the dependency injection pattern? Don't break the import chain. You should have a single composition root in your application where the components are wired together. The components themselves shouldn't be concerned with acquiring their dependencies.
Granted, in practice you have to deal with existing code (and other developers sceptical of DI) so you can't always do dependency injection "all the way down". In those cases you can expose the container as a global variable and pull the necessary dependencies from there.
Exposing the container as a global is essentially the Service Locator pattern. It has some disadvantages though.
Surely you can register somewhere which types you want to have imported/exported without having to scan the whole assembly. I don't know if this will help but here's a link I found after googling a bit: http://blogs.microsoft.co.il/blogs/zuker/archive/2010/10/17/mef-runtime-type-catalog-support-multi-registrations-in-runtime.aspx
精彩评论