MEF Strategy - looking for Compose point

Aug 23, 2010 at 2:09 AM

I have a MEFStrategy that is responsible for adding parts to the MEFContainer batch.   I'd like to have the Compose() accomplished in a transparent method so that one only has to add the extension and have MEF support.   Any recommendations from the gurus?

The first test gives a high level of how the MEFContainer works.  The second uses a Unity container with MEFExtension - it works as advertised but I'd like to lose the mefContainer.Compose() statement.

Blog/Source: http://www.global-webnet.net/blogengine/post/2010/08/22/Unity-Strategy-for-MEF.aspx

using System.ComponentModel.Composition;
using MEFContrib.Base;
using MEFContrib.Strategy;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestStrategyToLoadMEF
{
    [TestClass]
    public class MEFStrategyFixture
    {
        [TestMethod]
        public void PublicFromPublic()
        {
            var importer = new AllPublicImportOnly { ImportA = 1, ImportB = 1 };
            var exporter = new AllPublicExportOnly { ExportA = 5, ExportB = 10 };

            new MEFContainer()
                .AddPart(importer)
                .AddPart(exporter)
                .Compose();

            Assert.AreEqual(5, importer.ImportA);
            Assert.AreEqual(10, importer.ImportB);
        }

        [TestMethod]
        public void TestStrategyToLoadMEF()
        {
            var mefContainer = new MEFContainer();
            var mefExtension = new MEFStrategyExtension(mefContainer);

            // Instantiate unity container and add MEF extension
            var container = new UnityContainer().AddExtension(mefExtension);

            // Initialize MEF parts
            var importer = new AllPublicImportOnly { ImportA = 1, ImportB = 2 };
            var exporter = new AllPublicExportOnly { ExportA = 5, ExportB = 10 };

            // Buildup importer/exporter (strategy kicks in)
            container.BuildUp(importer);
            container.BuildUp(exporter);

            // Register importer instance emulating use in other area of app
            container.RegisterInstance<AllPublicImportOnly>(importer);

            // Resolve MEF and Unity classes
            var importResolved = container.Resolve<AllPublicImportOnly>();
            var classThatImports = container.Resolve<TestClassThatImports>();

            // MEF parts have not yet been composed (Strategy adds them to batch)
            Assert.AreEqual(1, importResolved.ImportA);
            Assert.AreEqual(2, importResolved.ImportB);
            
            // Compose MEF parts
            mefContainer.Compose();

            // After composition exported values should be in place
            Assert.AreEqual(5, importResolved.ImportA);
            Assert.AreEqual(10, importResolved.ImportB);

            // Unity setter injection 
            Assert.AreEqual(20, classThatImports.ImportedClass.TestValue);
        }
    }
    
    public class TestClassThatImports
    {
        [Dependency]
        public TestClassToImport ImportedClass { getset; }
    }

    public class TestClassToImport
    {
        public TestClassToImport()
        {
            TestValue = 20;
        }
        public int TestValue { getset; }
    }

    public class AllPublicImportOnly
    {
        [Import("a")]
        public int ImportA { getset; }
        [Import("b")]
        public int ImportB { getset; }
    }
    public class AllPublicExportOnly
    {
        [Export("a")]
        public int ExportA { getset; }
        [Export("b")]
        public int ExportB { getset; }
    }

}