locked
MEF with WinForms RRS feed

  • Question

  • I am trying to use MEF in my WinForms application.  I only wanted to inject it in a control that gets inserted into another control which is inserted in a TabControl on my mainForm.  The Property Components (shown below) in my UserControl is never intialized.  When I copy the property into my mainForm it is initialized.  The control that uses this is initialized using a new constructor (i.e. MyControl control = new MyControl()).  I am assuming it did not get initialized becuase the MyControl object was created with the new command.  Is this true?  If so, how do I add MEF in parts of my existing application without replacing all object creation that uses new to do imports?

        public partial class MyControl : UserControl, IPartImportsSatisfiedNotification
        {
            [ImportMany(typeof(IFoo))]
            public IEnumerable<IFoo> Components { get; set; }

            public MyControl()
            {
                InitializeComponent();
            }

            public void OnImportsSatisfied()
            {
                int i = 10;
            }
        }

    Thursday, July 12, 2012 10:04 PM

All replies

  • You would need to explicitly compose this object.  For details, see the "Composition" section of this article: http://msdn.microsoft.com/en-us/magazine/ee291628.aspx

    Note that you can compose parts anywhere in your application, but you do need to have access to (or create) a CompositionContainer to use to do the composition.


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Thursday, July 12, 2012 10:42 PM
  • I am a little confused by your response.  The code below shows more detail.  As shown this code works fine.  If I change the Form1 constructor to create the MyControl using new (i.e. MyControl myControl = new MyControl()) instead of the Import than the Foos collection in MyControl is not populated. 

    Is this because the container was created in the Form1 class and since MyControl is not instainated by an Import than the Imports in MyControl will not be generated?  Are you also saying that if I construct MyControl with new in Form1 then I should generate another CompositionContainer in MyControl to handle the Import?  How do I use the same CompositeContainer in multiple Forms?  Is there a staic property I can access or do I need to pass the container to all Forms?

    Thanks

        public partial class Form1 : Form, IPartImportsSatisfiedNotification
        {
            [ImportMany]
            private IEnumerable<IFoo> Foos { get; set; }
    
            [Import]
            MyControl MyControl {get; set;}
    
            private CompositionContainer _container; 
    
            public Form1()
            {
                ComposeMefContainer();
                InitializeComponent();
    
                this.Controls.Add(MyControl);
            }
    
    
            private void ComposeMefContainer()
            {
                var catalog = new AggregateCatalog(new DirectoryCatalog("."),
                new AssemblyCatalog(Assembly.GetExecutingAssembly()));
    
                var batch = new CompositionBatch();
                batch.AddPart(this);
    
                _container = new CompositionContainer(catalog);
                _container.Compose(batch);
            }
    
            public void OnImportsSatisfied()
            {
                int i = 10;
            }
        }
        [Export]
        public partial class MyControl : UserControl, IPartImportsSatisfiedNotification
        {
            [ImportMany]
            private IEnumerable<IFoo> Foos { get; set; }
    
            public MyControl()
            {
                InitializeComponent();
            }
    
            public void OnImportsSatisfied()
            {
                int i = 0;
            }
        }


    Friday, July 13, 2012 1:30 AM
  • I created two links on skydrive with examples

    "MEF WinForms Example 1" creates MyControl using new and hence the Foos collection is not created in MyControl

    "MEF WinForms Example 2" creates MyControl using an Import and in this case the Foos collection is created in MyControl

    https://skydrive.live.com/redir?resid=2CC3FBCF20291704!136&authkey=!AM0AQ8DE2XmejmU

    https://skydrive.live.com/redir?resid=2CC3FBCF20291704!137&authkey=!AL4COGljjBVSI50

    Thanks

    Friday, July 13, 2012 2:26 AM
  • " How do I use the same CompositeContainer in multiple Forms?  Is there a staic property I can access or do I need to pass the container to all Forms?"

    There is no static property - so you'd have to either make one, or pass the composition container around, or regenerate it as needed.

    Note that Silverlight does provide a CompositionInitializer class for this type of scenario (http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.compositioninitializer(v=vs.95).aspx), but it wasn't ported to the normal framework.  I have a blog post about this, including a link to a normal framework port (for WPF) here: http://reedcopsey.com/2010/03/26/mef-compositioninitializer-for-wpf/


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Friday, July 13, 2012 5:03 PM
  • Hi gentlemen,

    I am learning MEF with Windows Forms Application in Visual C# 2010 Express. I studied your discussions on the topics and I don't understand completely.

    To ifras2009:  The 2 examples you cited in https://skydrive.live.com/redir?.... are not accessible to me. Each time I clicked on one of them, I got: Internet Explorer cannot display the webpage for 2 days!!?? Is any alternative way you can show your 2 examples to the public?   

    To Reed C.:  I don't know anything WPF yet.  In doing MEF with Windows Forms Application in Visual C# 2010 Express, do I have to use WPF?

    I tried to launch a project of MEF with Windows Forms Application in my Visual C# 2010 Express by copying the code of ifras2009's MEF with WinForms:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.ComponentModel.Composition;
    namespace scMEFwithWindowsFormsApplication1
    {
        public partial class Form1 : Form, IPartImportSatisfiedNotification
        {
            [ImportMany]
            private IEnumerable<IFoo> Foos { get; set; }
            [Import]
            MyControl myControl { get; set; }
            private CompositionContainer _container;
            public Form1()
            {
                ComposeMefContainer();
                InitializeComponent();
                this.Controls.Add(myControl);
            }
            private void ComposeMefContainer()
            {
                var catalog = new AggregateCatalog(new DirectoryCatalog("."),
                    new AssemblyCatalog(AssemblyLoadEventArgs.GetExecutingAssembly()));
                var batch = new CompositionBatch();
                batch.AddPart(this);
                _container = new CompositionContainer(catalog);
                _container.Compose(batch);
            }
            public void OnImportsSatisfied()
            {
                int i = 10;
            }
            [Export]
            public partial class MyControl : UserControl, IPartImportsSatisfiedNotification
            {
                [ImportMany]
                private IEnumerable<IFoo> Foos { get; set; }
                public MyControl()
                {
                    InitializeComponent();
                }
                public void OnImportsSatified()
                {
                    int i = 0;
                }
            }
        }
     }

    I got the following errors: 1 Error The type or namespace name 'IPartImportSatisfiedNotification' could not be found (are you missing a using directive or an assembly reference?) C:\Documents and Settings\e1enxshc\my documents\visual studio 2010\Projects\scMEFwithWindowsFormsApplication1\scMEFwithWindowsFormsApplication1\Form1.cs 13 40 scMEFwithWindowsFormsApplication1
    2 Error The type or namespace name 'IFoo' could not be found (are you missing a using directive or an assembly reference?) C:\Documents and Settings\e1enxshc\my documents\visual studio 2010\Projects\scMEFwithWindowsFormsApplication1\scMEFwithWindowsFormsApplication1\Form1.cs 16 29 scMEFwithWindowsFormsApplication1
    3 Error The type or namespace name 'CompositionContainer' could not be found (are you missing a using directive or an assembly reference?) C:\Documents and Settings\e1enxshc\my documents\visual studio 2010\Projects\scMEFwithWindowsFormsApplication1\scMEFwithWindowsFormsApplication1\Form1.cs 21 17 scMEFwithWindowsFormsApplication1
    4 Error The type or namespace name 'IFoo' could not be found (are you missing a using directive or an assembly reference?) C:\Documents and Settings\e1enxshc\my documents\visual studio 2010\Projects\scMEFwithWindowsFormsApplication1\scMEFwithWindowsFormsApplication1\Form1.cs 52 33 scMEFwithWindowsFormsApplication1

    Gentlemen, please kindly help, answer and advise me how I can get it to wok for me.

    Thanks in advance,

    Scott Chang

    Thursday, July 19, 2012 1:03 PM