How to select the type of Import at runtime
-
Friday, October 08, 2010 8:37 PM
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
All Replies
-
Saturday, October 09, 2010 1:12 AM
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 8:41 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 9:58 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 10:11 AM
Wow, that's great - I look forward to seeing Jounce!
Greg

