Is there a way in MEF for a composed object to get a pointer to the ObjectComposer used?
trying to put up a nontrivial MEF application.
I wonder - is there a way for an object being composed to get a pointer to the ObjectComposer used to compose it?
The scenario is that the obejct may have to make inner compositions. I can push all links so far wia IMPORT attrobites on properties开发者_Go百科 or the constructor, but I miss a way for the composed object to get the object composer (so it could create a sub-composer for it's inner items).
Any standard / best practice way?
I assume that by "ObjectComposer", you mean the MEF container. I am not aware of a class or concept named ObjectComposer
.
(edit: the CompositionContainer documentation now explicitly mentions that you shouldn't put a container in itself. Hence the strike-through below.)
In your application start-up code, the container could register itself in itself:
CompositionContainer container = new CompositionContainer(...);
container.ComposeExportedValue<ExportProvider>(container);
Then you could import it anywhere like this:
[Import]
public ExportProvider Composer { get; set; }
However, what you are asking for here is a Service Locator, which has certain disadvantages. It is better to import more specific services, like an abstract factory.
ExportFactory
could also be helpful here, but that didn't make it into the .NET 4 release. You'll have to use the latest codeplex release of MEF if you want to try that.
This is how I do it:
Lots of my Exporters Import IMain.
[Import(typeof(IMain))]
public IMain Main { get; set; }
IMain is used as a container for an event service and the original composition service.
public interface IMain
{
ICompositionService CompositionService { get; set; }
EventPublisher Events { get; set; }
// more...
}
The initial composition is like this:
AggregateCatalog Catalog = new AggregateCatalog();
Catalog.Catalogs.Add(new DirectoryCatalog(Application.StartupPath));
CompositionContainer Container = new CompositionContainer(Catalog);
this.CompositionService = Container; // <- here I'm setting the IMain composition service
Container.ComposeParts(this);
Then when I want to compose a new object, I just pass it to the composition service:
MainPanel discoverPanel = new MainPanel();
Main.CompositionService.SatisfyImportsOnce(discoverPanel);
discoverPanel.Show();
精彩评论