MEF On-Demand Import

Mar 12, 2010 at 10:12 AM

I have a few UserControls in my application, which I'm exporting using a custom export attribute, and importing them using Lazy<UserControl, Metadata>[] controlCollection. This is giving me a list of the controls that were exported.

Then I'm looping thru the controlCollection and checking if( Metadata.Name == myRequiredUsercontrol) and then adding it to the region.

What if I want to import only myRequiredUserControl (I'll get this control name from a service)?? I want to avoid importing all the usercontrols and looping the collection.

 

Mar 12, 2010 at 1:44 PM

I have thought of having to perform this scenario, and without making a separate Export Attribute and doing a Lazy<UserControlSpecial, Meta> (no array) I could not accomplish with the basic knowledge I have of MEF. Hopefully someone has a simple thing to do without it being to complicated.

What I would think would be a awesome idea, (or even a separate CodePlex Extension) would be to use a ExportFactory that can be queried like a LINQ statement to completely drill down into the object I want MEF to give me.

Something like this would be really cool:

[Import(AllowDefault = true, AllowRecomposition)]
public ExportFactory<UserControl, MetaData> MyFactory {get; set;}

 

public void OnImportsSatisfied() {

var myControl = MyFactory.CreateExport()
.Where(metaData => metaData.Name == "MyControl1")
.Value;

//Use myControl 

}

Mar 12, 2010 at 6:36 PM

Could you mark the RequiredUserControl with an "IRequiredUserControl" interface that is set up with the "InheritedExport" attribute?  Then would you be able to mark the region with an import of that interface so that it knows to only add controls of the IRequiredUserControl type?  I've been successful at something similar with wrapper controls instead of regions.

Developer
Mar 12, 2010 at 8:22 PM

In general we do not have a way to import a single export form a set of exports. As 1quicknick mentioned you could do it with a unique contract. Another approach is to do an ImportMany into a custom collection which does the filtering for you see http://codepaste.net/ktdgoh for a example so in this case you would do something like:

[ImportMany]
public FilteringCollection<UserControl, Metadata> Controls { get; set; }

... in your constructor initialize the filter

this.Controls = new FilteringCollection<UserControl, Metadata>( (lazy) => lazy.Metadata.Name == "myRequiredUserControl");

Then while you still have a collection it should contain only the one item (assuming there is exactly one matching your metadata filter).

Mar 12, 2010 at 8:38 PM

I still think it would be cool to have a set of extensions to the ExportFactory to query for a particular instance you want. Maybe a CodePlex thing...

Mar 29, 2010 at 6:08 AM

Thank you very much.

I also found this AdaptingCollection useful, http://mef.codeplex.com/Thread/View.aspx?ThreadId=64387 (Not yet tried for my problem, but looks quite promising)