views:

196

answers:

1
+2  Q: 

MEF + SL4 question

I'm working on an app in the Silverlight 4 RC and i'm taking the oppertunity to learn MEF for handling plugin controls. I've got it working in a pretty basic manor, but it's not exactly tidy and I know there is a better way of importing multiple xap's.

Essentially, in the App.xaml of my host app, I've got the following telling MEF to load my xap's:

AggregateCatalog catalog = new AggregateCatalog();

DeploymentCatalog c1 = new DeploymentCatalog(new Uri("TestPlugInA.xap", UriKind.Relative));
DeploymentCatalog c2 = new DeploymentCatalog(new Uri("TestPlugInB.xap", UriKind.Relative));

catalog.Catalogs.Add(c1);
catalog.Catalogs.Add(c2);

CompositionHost.Initialize(catalog);

c1.DownloadAsync();
c2.DownloadAsync();

I'm sure I'm not using the AggregateCatalog fully here and I need to be able to load any xap's that might be in the directory, not just hardcoding Uri's obviously....

Also, in the MainPage.xaml.cs in the host I have the following collection which MEF puts the plugin's into:

[ImportMany(AllowRecomposition = true)]
public ObservableCollection<IPlugInApp> PlugIns { get; set; }

Again, this works, but I'm pretty sure I'm using ImportMany incorrectly....

Finally, the MainPage.xaml.cs file implements IPartImportsSatisfiedNotification and I have the following for handling the plugin's once loaded:

public void OnImportsSatisfied()
{
    sp.Children.Clear();

    foreach (IPlugInApp plugIn in PlugIns)
    {
        if (plugIn != null)
            sp.Children.Add(plugIn.GetUserControl());
    }
}

This works, but it seems filthy that it runs n times (n being the number of xap's to load). I'm having to call sp.Children.Clear() as if I don't, when loading the 2 plugin's, my stack panel is populated as follows:

TestPlugIn A TestPlugIn A TestPlugIn B

I'm clearly missing something here. Can anyone point out what I should be doing? Thanks!

+1  A: 

I think most of what you are doing is fine. Although ObservableCollections do support notifications of individual elements being added and removed, MEF doesn't take advantage of this. In your case it will simply clear the collection and then add all the plugins. Since you are using OnImportsSatisfied for the change notification, you don't even need an ObservableCollection. You could just use an IEnumerable for your import.

To add flexibility in downloading different xaps, I would expose a service in your container that can be imported and that provides the functionality to download a xap given a url. Then any component in your container can trigger a download, and the url to download can come from whatever source you deem appropriate.

Daniel Plaisted
Thanks, that's pretty much what I've gone with and seems to be OK for my needs
Tom Allen