How to create new objects from MEF import

I am a little confused by MEF, I thought I started to understand, but it seems that I'm not quite there.

So, I have a list of XML test steps that I want to read. The idea is that the main application knows nothing about types at runtime.

<TestSteps> <TestRunner xsi:type="SimulateDc" Measurement="54"/> <TestRunner xsi:type="MeasureDc" Output="1"/> </TestSteps> 

So, I have a base type with a static class of "results" that allows me to save information for the transition between steps (the Output attribute in XML above). Test handlers are exported by MEF here, I read them at runtime, and then pass Type to go to the XML serializer to create a list of handlers. It all works, and I get a list of test participants. I have a DataTemplate export for each type, so when I use Content Control, it knows how to draw myself. Everything seems beautiful, but I think I was mistaken in my thinking process.

One of the problems is that now I want to bind the imported handlers to some equipment. equipment processing routines are designed to handle even more MEF import operations.

So, with this interface:

 public interface IMeasureHW { double Measure(); } 

Then using this:

 [Export("MeasureDc", typeof(IMeasureHW))] public class MeasureDcHW : IMeasureHW { public double Measure() { return 54.0; } } 

Then in one of my handlers, I did this:

 [Import("MeasureDc", typeof(IMeasureHW))] IMeasureHW hardware { get; set; } 

My import is done as follows:

 protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var catalog = new AggregateCatalog(); catalog.Catalogs.Add(new DirectoryCatalog(".")); catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly())); _container = new CompositionContainer(catalog); _container.ComposeParts(this); MainWindow.Show(); } 

However, I assume that serializing the XML above and using Type information, as I would do, would definitely mean that the import would be null, so it is implied that my thought patterns for design are wrong.

I managed to get it working by exporting the CompositionContainer, and then after loading the XML, I can do this:

 foreach (TestRunnerBase t in testSteps) { _container.SatisfyImportsOnce(t); } 

But for me this is a bit wrong, since the original list of imported testing steps is not used for anything other than type. So I thought that I should export the data as parts of the MEF, and then export the handlers myself, and then when I read the data from the XML in my list, do I ask the handler from the list? If that makes sense?

I could not understand how you would link them this way, since the MEF composition is processed in my App.xaml.cs , and the testing steps are in the view model elsewhere. I was thinking about how to use metadata to bind data to a handler, and then search for the appropriate handler in the imported list. Perhaps I should do some initial parsing to create a dictionary to speed up the search?

The more you need to do this? Any help is appreciated, I am already pretty easy in separating hair, so I can not afford to lose more

+4
source share
1 answer

Please correct me if I am wrong. It seems you could achieve your goal by catching on an import: the innermost one is your TestRunner collection, then the hardware classes, and then finally the content control.

In the example below, these are Class2 : MySubInterface , Class1 : MyInterface and Program respectively:

 /////inner using MyHostingNamespace; namespace ClassLibrary1 { [Export("class2", typeof(MySubInterface))] class Class2 : MySubInterface { public string MyProperty { get; set; } public Class2() { MyProperty = "Class2"; } } } ////middle using MyHostingNamespace; namespace ClassLibrary1 { [Export("class1", typeof(MyInterface))] public class Class1 : MyInterface { [Import("class2", AllowDefault=true)] MySubInterface myClass2; public string MyProperty {get;set;} public Class1() { AggregateCatalog catalog = new AggregateCatalog(); catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly())); CompositionContainer _container = new CompositionContainer(catalog); _container.ComposeParts(this); MyProperty = myClass2.MyProperty; } } } ////outer namespace MyHostingNamespace { class Program { [Import("class1")] public MyInterface class1; public Program() { AggregateCatalog catalog = new AggregateCatalog(); catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly())); catalog.Catalogs.Add(new DirectoryCatalog(".")); CompositionContainer _container = new CompositionContainer(catalog); _container.ComposeParts(this); } static void Main(string[] args) { Program p = new Program(); Console.WriteLine(p.class1.MyProperty); } } public interface MyInterface { string MyProperty { get; set; } } public interface MySubInterface { string MyProperty { get; set; } } } 
0
source

All Articles