none
Why is CompositionHost and CompositionInitializer not part of desktop development RRS feed

  • Question

  • Glenn Block had written a CompositionInitializer for the desktop and I was wondering why this was MEF for .NET framework 4.5?  Is there a preferred way to do the following?  BTW, I know I can Import Foo and this will work.  But I was trying to make it work when I instantiate Foo using new.  I am trying to incorporate MEF in an exisiting project in which some objects are created with new operator.  Is there another preferred method to do this?

        class Program
        {
            static void Main(string[] args)
            {
                Test mytest = new Test();
            }
        }
    
        public class Test
        {
            public Test()
            {
                ComposeMefContainer();
    
                Foo foo = new Foo();
            }
    
            private void ComposeMefContainer()
            {
                CompositionContainer _container;
                var catalog = new AggregateCatalog(new DirectoryCatalog("."),
                              new AssemblyCatalog(Assembly.GetExecutingAssembly()));
                _container = new CompositionContainer(catalog);
                _container.ComposeParts(this);
    
                CompositionHost.Initialize(_container);
    
            }
        }
    
        public class Foo
        {
            [Import]
            Bar abar;
    
            public Foo()
            {
                CompositionInitializer.SatisfyImports(this);
            }
        }
    
        [Export]
        public class Bar
        {
            public string Name {get; set;}
    
            public Bar()
            {
                Name = "Tom";
            }
        }


    • Edited by jfras2009 Saturday, May 4, 2013 5:13 PM
    Saturday, May 4, 2013 5:11 PM

Answers

  • John,  I chatted with a dev on the MEF team about your question and pasting his response below. Hope this answers your question.

    "

    All that he has to do is to have a public static container which he initializes and uses to do this work:

    For example:

    My changes to his code are in bold italics.  Please make sure he understands this is not our recommended approach, it is however pretty much exactly what he asked for.  We didn’t ship it in Desktop because we couldn’t come up with a design for it that worked in the desktop scenarios.

    using System;

    using System.Collections.Generic;

    using System.ComponentModel.Composition;

    using System.ComponentModel.Composition.Hosting;

    using System.Linq;

    using System.Reflection;

    using System.Text;

    using System.Threading.Tasks;

    publicclassCompositionHost

    {

        internalstaticCompositionContainer_container = null;

        publicstaticvoidInitialize(CompositionContainercontainer)

        {

            _container = container;

        }

        publicstaticCompositionContainerCompositionInitializer { get{ return_container asCompositionContainer; } }

    }

    class Program

    {

        static void Main(string[] args)

        {

            Test mytest = new Test();

        }

    }

    public class Test

    {

        public Test()

        {

            ComposeMefContainer();

            Foo foo = new Foo();

        }

        private void ComposeMefContainer()

        {

            CompositionContainer _container;

            var catalog = new AggregateCatalog(new DirectoryCatalog("."),

                          new AssemblyCatalog(Assembly.GetExecutingAssembly()));

            _container = new CompositionContainer(catalog);

            _container.ComposeParts(this);

            CompositionHost.Initialize(_container);

        }

    }

    public class Foo

    {

        [Import]

        Bar abar;

        public Foo()

        {

            CompositionHost.CompositionInitializer.SatisfyImportsOnce(this);

        }

    }

    [Export]

    public class Bar

    {

        public string Name { get; set; }

        public Bar()

        {

            Name = "Tom";

        }

    }"

    • Marked as answer by jfras2009 Monday, July 15, 2013 9:01 PM
    Monday, July 8, 2013 7:57 PM

All replies

  • Hi Jfras,

    Welcome to the MSDN Forum.

    I am trying to involve some other one into this case. It will take some time, wait it patiently, please.

    Thank you for your understanding and support.

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, May 7, 2013 9:02 AM
    Moderator
  • CompositionInitializer was written as a special case scenario for Silverlight, since access to the file system was not possible and a good way to create a catalog did not exist. (Some of this history is lost to me, since it was before my time).  I don`t expect CompositionInitializer to ever come into the desktop framework.

    The thing that I am unsure is what you are trying to do.  If the legacy code as you mention does a new on a type say Foo in this example and you cannot access the code, then I would expect that you could start your composition from Foo. 

    In addition for the scenario for vanialla C# objects has a feature called registration builder which lets you specify rules with which you can attribute parts. 

    http://blogs.msdn.com/b/bclteam/archive/2011/11/01/getting-started-with-convention-based-part-registration-in-mef-version-2.aspx

    http://blogs.msdn.com/b/bclteam/archive/2011/11/03/overriding-part-registration-conventions-with-the-mef-attributes-nick.aspx

    The registration builder class should allow you to take existing code, write rules so that the existing code becomes proper composable MEF parts and then compose correctly.

    hope that helps.  let me know in case of any further questions

    cheers

    -alok shriram

    program manager

    .Net Framework

    Friday, June 7, 2013 5:04 PM
  • Hi alok

    How will I handle the simple example that's shown above?

    How do you use CompositionHost.SatisfyImports()? Is this only for windows store app?

    Tuesday, June 11, 2013 2:44 AM
  • Hi jfras2009,

    Alok is out of office this week. I've let him know about your follow up question anyways.

    Nibu


    Blog: http://ntcoder.com/bab


    Posts are provided as is without warranties or guaranties.

    Tuesday, June 11, 2013 8:07 AM
    Moderator
  • Hi Jfras,

    First off CompositionHost class exists for only Silverlight. 

    SatifyImportsOnce is the method that exists for windows store apps.

    If I understand correctly Test is a pre-written class and you don`t want to touch this.  Below this you Foo and Bar which are new classes which you can touch and change the code to. 

    When you have written new Foo(), you loose any decoupling that you could have gotten, since now you are tied to the type Foo.

    In this case I would build my container and start my DI chain from there. In the constructor for the Foo class do something like the follows. (Execuse the crappy formatting)

    TypeCatalog 

    catalog = newTypeCatalog(typeof(Bar), typeof(Foo));

               

    CompositionContainercontainer = newCompositionContainer(catalog);

                container.ComposeParts(

    this);

    This should get your composition going.  However a cleaner way to factor this (Since you have some legacy code) would be use RegistrationBuilder and do a rule based approach if possible. The articles above written by Nick should give you a good starting point.

    Hope that helps

    Tuesday, June 18, 2013 10:19 PM
  • Hi Jfras,

    Hope Alok's reply helped answer your question. Awaiting your response.

    Thanks,

    Nibu


    Blog: http://ntcoder.com/bab


    Posts are provided as is without warranties or guaranties.

    Monday, June 24, 2013 9:43 AM
    Moderator
  • I want to start the composition in test , not in foo or bar. I got by my problem by using CommonServiceLocator but I want to know if there is another way to do this. Thanks John
    Tuesday, June 25, 2013 2:47 AM
  • John,  I chatted with a dev on the MEF team about your question and pasting his response below. Hope this answers your question.

    "

    All that he has to do is to have a public static container which he initializes and uses to do this work:

    For example:

    My changes to his code are in bold italics.  Please make sure he understands this is not our recommended approach, it is however pretty much exactly what he asked for.  We didn’t ship it in Desktop because we couldn’t come up with a design for it that worked in the desktop scenarios.

    using System;

    using System.Collections.Generic;

    using System.ComponentModel.Composition;

    using System.ComponentModel.Composition.Hosting;

    using System.Linq;

    using System.Reflection;

    using System.Text;

    using System.Threading.Tasks;

    publicclassCompositionHost

    {

        internalstaticCompositionContainer_container = null;

        publicstaticvoidInitialize(CompositionContainercontainer)

        {

            _container = container;

        }

        publicstaticCompositionContainerCompositionInitializer { get{ return_container asCompositionContainer; } }

    }

    class Program

    {

        static void Main(string[] args)

        {

            Test mytest = new Test();

        }

    }

    public class Test

    {

        public Test()

        {

            ComposeMefContainer();

            Foo foo = new Foo();

        }

        private void ComposeMefContainer()

        {

            CompositionContainer _container;

            var catalog = new AggregateCatalog(new DirectoryCatalog("."),

                          new AssemblyCatalog(Assembly.GetExecutingAssembly()));

            _container = new CompositionContainer(catalog);

            _container.ComposeParts(this);

            CompositionHost.Initialize(_container);

        }

    }

    public class Foo

    {

        [Import]

        Bar abar;

        public Foo()

        {

            CompositionHost.CompositionInitializer.SatisfyImportsOnce(this);

        }

    }

    [Export]

    public class Bar

    {

        public string Name { get; set; }

        public Bar()

        {

            Name = "Tom";

        }

    }"

    • Marked as answer by jfras2009 Monday, July 15, 2013 9:01 PM
    Monday, July 8, 2013 7:57 PM
  • Hi John

    Are your questions answered?

    Thanks,
    Nibu


    Blog: http://ntcoder.com/bab


    Posts are provided as is without warranties or guaranties.

    Monday, July 15, 2013 1:43 PM
    Moderator