none
How to select the type of Import at runtime

    Question

  • Hi,

    Am new to MEF and have a basic question:  How do I change the type that gets imported at runtime based on runtime data?  Say for example, User A likes screen layout A, so I want to import UserControlA, and user B likes screen layout B, so I want to import UserControlB.

    It seems that all MEF Imports are static, meaning they can't be changed. 

    Greg

    Friday, October 08, 2010 8:37 PM

Answers

  • That's a great start. I'll give you an example from a framework I'm developing that will be  released shortly.

    Here is the definition I use to export views:

    namespace Jounce.Core.View
    {
        /// <summary>
        ///     Export a view 
        /// </summary>
        [MetadataAttribute]
        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = false)]
        public class ExportAsViewAttribute : ExportAttribute 
        {
            public ExportAsViewAttribute(string viewType) : base(typeof(UserControl))
            {
                ExportedViewType = viewType;
                IsShell = false;
                Category = string.Empty;
                CommandName = string.Empty;
                ToolTip = string.Empty;
            }
    
            /// <summary>
            ///     The view type
            /// </summary>
            public string ExportedViewType { get; private set; }
    
            public bool IsShell { get; set; }
    
            public string Category { get; set; }
    
            public string CommandName { get; set; }
    
            public string ToolTip { get; set; }
        }
    }
    

    Then, when I have a view, I can tag it with extra information, like this:

    namespace SimpleNavigation.Views
    {
        [ExportAsView("GreenCircle",Category="Navigation",CommandName="Circle",ToolTip = "Click to view a green circle.")]
        public partial class GreenCircle
        {
            public GreenCircle()
            {
                InitializeComponent();
            }
        }
    }
    

    Finally, when my navigation hook is pulling in items, it can inspect the meta data and filter accordingly, like this:

    /// <summary>
    ///     Grab the full list of views
    /// </summary>
    [ImportMany(AllowRecomposition = true)]
    public Lazy<UserControl, IExportAsViewMetadata>[] Views { get; set; }
    
    public void _WireButtonInfo()
    {
        // filter only those views that are in the navigation category
        foreach(var v in from viewInfo in Views where viewInfo.Metadata.Category.Equals("Navigation")
                            select Tuple.Create((ICommand)NavigateCommand,
                            viewInfo.Metadata.ExportedViewType, 
                            viewInfo.Metadata.CommandName, 
                            viewInfo.Metadata.ToolTip))
        {
            _buttonInfo.Add(v);
        }
    }


     

    Hope that gives some more detailed insight - I'll be releasing Jounce in the next few weeks or sooner.

    Saturday, October 09, 2010 9:58 AM

All replies

  • Not at all. You need to research meta data. Basically, you provide a facility to pull in information about plugin A and B. You pull in the meta data but not the actual controls or layouts - the user selects the meta data, and then you load the value (i.e. the control or layout) for it. It is absolutely possible but requires the metadata filtering I described.

     

    Saturday, October 09, 2010 1:12 AM
  • OK, have read up on the Metadata data.  I think this is how you are saying it would be done (psuedo code):

    [Import(typeof(MyUserControl))] //Import type is of MyUserControl

    [ImportMany] //Import All Exported MyUserControls

    IEnumerable<MyUserControl> AllControls

    MyUserControl TheControlThatWillBeShown

    PageConstructor()

    {

               CompositionInitializer.SatisfyImports(this) //Satisfy the imports

               if (UserOptionA)

                     //Pull the Control with MetaData of OptionA out and assign to TheControlThatWillBeshown.

                Else

                     //Pull the Control with MetaData of OptionB out and assign to TheControlTheWillBeShown.

    }

    Saturday, October 09, 2010 8:41 AM
  • That's a great start. I'll give you an example from a framework I'm developing that will be  released shortly.

    Here is the definition I use to export views:

    namespace Jounce.Core.View
    {
        /// <summary>
        ///     Export a view 
        /// </summary>
        [MetadataAttribute]
        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = false)]
        public class ExportAsViewAttribute : ExportAttribute 
        {
            public ExportAsViewAttribute(string viewType) : base(typeof(UserControl))
            {
                ExportedViewType = viewType;
                IsShell = false;
                Category = string.Empty;
                CommandName = string.Empty;
                ToolTip = string.Empty;
            }
    
            /// <summary>
            ///     The view type
            /// </summary>
            public string ExportedViewType { get; private set; }
    
            public bool IsShell { get; set; }
    
            public string Category { get; set; }
    
            public string CommandName { get; set; }
    
            public string ToolTip { get; set; }
        }
    }
    

    Then, when I have a view, I can tag it with extra information, like this:

    namespace SimpleNavigation.Views
    {
        [ExportAsView("GreenCircle",Category="Navigation",CommandName="Circle",ToolTip = "Click to view a green circle.")]
        public partial class GreenCircle
        {
            public GreenCircle()
            {
                InitializeComponent();
            }
        }
    }
    

    Finally, when my navigation hook is pulling in items, it can inspect the meta data and filter accordingly, like this:

    /// <summary>
    ///     Grab the full list of views
    /// </summary>
    [ImportMany(AllowRecomposition = true)]
    public Lazy<UserControl, IExportAsViewMetadata>[] Views { get; set; }
    
    public void _WireButtonInfo()
    {
        // filter only those views that are in the navigation category
        foreach(var v in from viewInfo in Views where viewInfo.Metadata.Category.Equals("Navigation")
                            select Tuple.Create((ICommand)NavigateCommand,
                            viewInfo.Metadata.ExportedViewType, 
                            viewInfo.Metadata.CommandName, 
                            viewInfo.Metadata.ToolTip))
        {
            _buttonInfo.Add(v);
        }
    }


     

    Hope that gives some more detailed insight - I'll be releasing Jounce in the next few weeks or sooner.

    Saturday, October 09, 2010 9:58 AM
  • Wow, that's great - I look forward to seeing Jounce!

    Greg

    Saturday, October 09, 2010 10:11 AM