I've had a few questions about MEF recently, but here's the big one -- is it really all-or-nothing, as it appears to be?
开发者_如何学编程My basic application structure is simply an app, several shared libraries that are intended to be singletons, and several different plugins (which may implement different interfaces). The app loads the plugins, and both the app and all plugins need to access the shared libraries.
My first go at MEF was fairly successful, although I made some stupid mistakes along the way because I was trying so many different things, I just got confused at times. But in the end, last night I got my smallish test app running with MEF, some shared libraries, and one plugin.
Now I'm moving onto the target app, which I already described. And it's the multiple plugins part that has be a bit worried.
My existing application already supports multiple plugins with different interfaces by using Reflection. I need to be able to uniquely identify each plugin so that the user can select one and get the expected behavior exposed by that plugin. The problem is that I don't know how to do this yet... but that's the topic of a different question.
Ideally, I'd be able to take my existing plugin loader and use it as-is, while relying on MEF to do the shared library resolution. The problem is, I can't seem to get MEF to load them (i.e. I get a CompositionException when calling ComposeParts()) unless I also use MEF to load the plugin. And if I do this, well... then I need to know how to keep track of them as they get loaded so the user can select one from a list of plugins.
What have your experiences been with trying to mix and match these approaches?
MEF is designed to let you easily load plugin assemblies. If you have control over the plugins (by which I mean that you can add MEF export attributes) then there is no need to keep your own plugin loader which uses reflection. MEF does all that for you.
That being said, "mixing and matching" MEF with other technologies is certainly possible. It sounds like your problem is that if you use your own plugin loader, you don't add those plug-ins to the MEF container. As a result, you get a CompositionException
for parts which try to import the selected plug-in.
To add a plugin that you loaded with your own code to the MEF container, you can use the ComposeExportedValue
like this:
container.ComposeExportedValue<IPlugin>(selectedPlugin);
edit: I see what you mean now by "all or nothing". Your problem is that in order to be able to import parts with MEF, you also need to construct the object with MEF. This problem then cascades to the object which normally created that object, etc. all the way to the application root.
To avoid this "all or nothing" effect, you can compromise by exposing the MEF container as a global variable (i.e. static field). That way, classes can access the MEF container and pull exports from it, e.g. by calling Program.Container.GetExportedValue<MyDependency>()
in the constructor.
edit2: If you have an object that was not constructed by MEF, then there are two ways to add it to the container.
The first is to call container.ComposeExportedValue<IMyContractType>(myObject);
.
The second is to return the object in a property getter, and then mark the property itself with an [Export(typeof(SomeType))] attribute.
精彩评论