Nested Containers and Combining Parts for ImportMany

Jan 15, 2010 at 2:17 AM

As I understand it if you have nested containers, they are basically just a series of export providers and the first export provider that can supply matching parts stops the evaluation.

I have questions about how this works with ImportMany.

- I currently have no exports in my leaf container and do have matching exports in deeper containers. I am not finding these inner exports. If there is an InnerMany and the first export provider does not provide any matches, does evaluation continue to the second container (in which case I have a different problem causing my missing exports).

- What I actually want to do is merge the collection across multiple containers. I could retrieve the matching exports in the outer container and explicitly add them to the inner container. While ugly, that would work in my scenario. To provide this capability by extending MEF, what would I need to do? I would override the export provider with a custom export provider, but what would it need to overwrite.

Thanks for any insight on this!


Jan 15, 2010 at 3:18 AM

Follow on question...

If I have values that have been explicitly placed in the container (via AddExport), will the behavior be identical to that of items in catalogs?


Jan 15, 2010 at 11:14 PM

I'm a little deeper into this and very uncertain of how to make this work. There are actually a few more layers, but I think this captures the problem.

I have a layer which opens at startup which pulls information from the command line, app.config and setting and places them as exported parts with contrats built from their corresponding names. I also load a series of types via directory catalogs. Again, I know nothing about what is being loaded. This is my outer catalog and let's say it includes a Class Foo which has a string import with an explicit contract name Bar.

One of the things I find in this initial load is the name of a script file as an XML file. The code for reading this file is retrieved from one of the assemblies loaded in the initial container. All of the attributes on the root element are read and placed into a container which is a child of the parent container. There will be multiple script files and they should share the information from the initial container, but they should not share the informaton from the root of the XML file.

The problem is that the Bar value for the Foo class in the initial container may be (in the case of my current issue, is) fulfilled by the inner container values read from the script file and should be different for each script file.

If I explictly add the parent catalog to the child container, the value of Bar is correctly resolved. However, I get multiple occurrences of types. I do not understand why but I suspect it is becuase the same catalog is in the parent and child.

If I create a new, not nested child container with the parent catalg, I do not have access to the configuration values in the parent.

If I use a child container but delay adding the catalog, I may be able to get the behavior I need, but I'll have ot have an extra container just to load the script files.  Does this sound like the best approach to this admittedly complex scenario.


Jan 15, 2010 at 11:25 PM
Edited Jan 15, 2010 at 11:25 PM

If you want the part to only appear in the child container and not in the parent, you should either use a filtered catalog, or have a different catalog on the child that includes the part, and not have it on the parent. Otherwise if you do an ImportMany you will get 2 instances of the part, one from the child and the parent.

As far as having Bar in the Parent import from the Child, that's not a scenario we in general think or hear about. The idea of hierarchical containers is to keep the parent ignorant of the children, only the children know. If you want the parent to import anything from the child, it's going to be problematic if there are many children, which is usually the case.

One way you could solve it, assuming you need to do  this is have a shared data part in the parent which is shared by the child. That part can have some sort of dictionary that the child can use to store it's data. The part in the parent that needs the data uses the data part and passes it the same key to get that data. The main thing to solve here would be how the parent then knows the key that the child is using. You would likely need some sort of convention or protocol, maybe an event from the child?