Donnerstag, 19. Dezember 2013

Generic base class for composing objects using MEF

If MEF is used extensively, it is not practicable to implement the composition for every class or type that has to be compsed. Why not create a generic base class that can load all of the objects that we need.
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;

public class Composer<T>
{
    public T Compose<T>()
    {
        Compose();

        if (Imports == null)
            return default(T);

        return (T)(object)Imports.FirstOrDefault();
    }
        
    private static AggregateCatalog _catalog;

    private CompositionContainer _container;

    [ImportMany]
    public IEnumerable<T> Imports { get; set; }

    private void Compose()
    {
        // an aggregate catalog that combines multiple catalogs
        var catalog = new AggregateCatalog();

        // load all assemblies in the current directory
        catalog.Catalogs.Add(new DirectoryCatalog(".", "*.exe"));

        Compose(catalog);
    }

    private void Compose(AggregateCatalog catalog)
    {
        _catalog = catalog;

        // create the CompositionContainer with the parts in the catalog
        _container = new CompositionContainer(_catalog);

        // fill the imports of this object
        try
        {
            _container.ComposeParts(this);
        }
        catch (CompositionException compositionException)
        {
            Console.WriteLine(compositionException.ToString());
        }
    }
}

This class can now be used to Compose objects that are marked with the ExportAtribute.
[Export(typeof(ComposeableClass))]
public class ComposeableClass
{
}
[TestMethod]
public void GenericComposerComposeTest()
{
    var composer = new Composer<ComposeableClass>();
    var part = composer.Compose<ComposeableClass>();
    Assert.IsNotNull(part);
}

Keine Kommentare: