CompositionContainer.AddPart() for every object?

Sep 10, 2008 at 10:44 PM

Just having a look at the framework.  I created myself a class which deals with catalogues and containers, when a container changes it fires an event to alert the concerned parties.

In my code, I had this statement:

However, it looks like I also need to add every object which has an [Import] attribute on top of a property - is this correct? I could only get my import to work when I had included my main window as a part.

If so, do you not think this could lead to difficult to manage code and dependencies? I can imagine developers adding the attribute but forgetting to register the class, hence the value always being null.

Or have I missed something?


Sep 11, 2008 at 12:57 AM

Thanks Ben for your feedback!

To use a part, which has imported properties, you do not have to add an instance of that part to the container. Instead, you can simply decorate an [Export] attribute on the part. Since you are using catalogs, that part can be discovered by the container automatically and you can ask an instance of that part from the container by using container.GetExportedObject.

Assuming your host window has some imported dependencies, yes, you will need to to add it to the container explicitly, because you definitely want the dependencies of your current instance of host window are satified rather than asking container to give you a new instance of your host window. Normally, you will need to do this only for host window and nothing else. Container is supposed to create all others along your dependency chain.

We are still looking for a better way for hosting story. What is your perferred way of hosting?


Sep 17, 2008 at 12:09 AM
Hi Zhenlan,

Thanks for your reploy.  If I understand correctly,  Program.cs should create my CompositionContrainer and catalog and add itself?  Then use Import to gain access to Form1, MEF creates it and as such can resolve all of the [Import] statements?  At which point, to access any object which uses MEF, it needs to have a Import\Export? 

For me, this will cause confusion as it makes the code more coupled.  If my application was only using MEF for extensibility and as such, only initialised the container when it was just about to be used, I can imagine it would be difficult to use the initialise objects in other locations (as you would also need to initialise the object).  This goes for existing applications, if I wanted to use MEF for my logging system, I would need to change large parts of my application for this to work, just to make sure that my container knows about all of the objects with Import attributes.

What would I like? Ideally for MEF just to 'know' if the object has an [Import] directive.  Like how it goes with Export, I want it just to know where it needs to step in and resolve the Import. 

Fundamentally, I want my catalog to look after both importing and exporting.  Then, all I need to do is initialise my container, add in catalogs for finding everything and then use my application. Having to use [Import] to get access to  objects which also uses [Import] just sounds like a lot of effort.

I hope that makes sense??


Sep 17, 2008 at 9:30 PM
The container does handle both imports and exports.  But it only knows about objects that it created and objects that you explicitly added to it.  It sounds like you want MEF to do something like scan all objects in memory and look to see which ones have Import attributes.  I don't think that's possible and even if it is I don't think it would be a good idea.

Generally the idea with MEF is that MEF will create most of the objects that have import or export attributes on them.  So your Program might import your MainFormContract, which would be exported by your MainForm.  Your MainForm would import an ILogger, a list of IViewProviders, or whatever, and those in turn would be exported by the classes that implement them.  So when the dependencies on your Program are resolved, it will create the whole chain of your MainForm, your ILogger, etc and set all the imports appropriately.  When you do it like this it should actually decrease coupling, since you don't have to pass the container to all your objects and you don't have to pass object instances around as much either.

Does this make sense?  I know it might require some significant changes to work this in to an existing application.