tags:

views:

115

answers:

1

I've got a property defined on a class that has the importManyAttribute defined for it, the declaration is as follows:

public const string FontStyleProvidersPropertyName = "FontStyleProviders";
[ImportMany(typeof(IFontStyleProvider), RequiredCreationPolicy = CreationPolicy.Shared, AllowRecomposition=true)]
public List<IFontStyleProvider> FontStyleProviders { get; set; }

on first run I build my composition container as follows

private CompositionContainer BuildCompositionContainer()
{
    //build our composable parts catalog
    Assembly executingAssembly = Assembly.GetExecutingAssembly();
    CompositionContainer applicationContainer;
    string localPath = Path.GetDirectoryName(executingAssembly.Location);

    try
    {
        aggregateCatalog = new AggregateCatalog();
        aggregateCatalog.Catalogs.Add(new AssemblyCatalog(executingAssembly));

        if (!Directory.Exists(Path.Combine(localPath, ApplicationExtensionsPath)))
        {
            Directory.CreateDirectory(Path.Combine(localPath, ApplicationExtensionsPath));
        }

        exportsCatalog = new DirectoryCatalog(Path.Combine(localPath, ApplicationExtensionsPath));

        aggregateCatalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(localPath, ApplicationExtensionsPath)));

        //create a composition container
        return applicationContainer = new CompositionContainer(aggregateCatalog);
    }
    catch (Exception e)
    {
        Debug.Fail("Catalog Construction Failed", e.StackTrace);
        throw;
    }
}

At this point, everything works as expected, but I can't seem to trigger re-composition on "this" class instance. I have an import method as follows:

private void Import()
{
    exportsCatalog.Refresh();
    CompositionBatch batch = new CompositionBatch();
    batch.AddPart(this);
    applicationContainer.Compose(batch);

    var copy = PropertyChanged;
    if (copy != null)
    {
        copy(this, new PropertyChangedEventArgs(FontStyleProvidersPropertyName));
        copy(this, new PropertyChangedEventArgs(MessageContainerViewModelsPropertyName));
    }
}

It finds new types in the ApplicationExtensionPath folder used by the exportsCatalog just fine, but it never actually re-builds FontStyleProviders (or MessageContainerViewModels)

I've been through the documents a few times and I can't seem to figure out why.

+2  A: 

The problem is you aren't actually adding the catalog which you call Refresh() on to the AggregateCatalog. Change this:

exportsCatalog = new DirectoryCatalog(Path.Combine(localPath, ApplicationExtensionsPath));
aggregateCatalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(localPath, ApplicationExtensionsPath)));

To this:

exportsCatalog = new DirectoryCatalog(Path.Combine(localPath, ApplicationExtensionsPath));
aggregateCatalog.Catalogs.Add(exportsCatalog);

Also, once your class has been composed once you shouldn't compose it again. Just calling exportsCatalog.Refresh() will be enough to cause recomposition.

Daniel Plaisted