I am a little confused by MEF, I thought I had begun to understand it but it appears I am not quite there.
So, I have a list of test steps in XML that I want to read in. The idea is that the main application doesn't know anything about the types at run time.
<TestSteps>
<TestRunner xsi:type="SimulateDc" Measurement="54"/>
<TestRunner xsi:type="MeasureDc" Output="1"/>
</TestSteps>
So I have a base type with a static "results" class that allows me to save information to pass between steps (The Output
attribute in the XML above). The test handlers here are exported by MEF, I read them in at runtime and then get the Type
to pass into the XML serializer to create a list of handlers. This all works and I get a list of test runners. I have a DataTemplate
export for each type here so when I use a Content Control it knows how to draw itself. All all seems fine, however I think I have gone wrong in my thought process.
One issue is that I now want to tie the imported handlers to some hardware. the hardware handling routines are intended to be handled by yet more MEF imports
So with an interface like this:
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 test handlers I have done this:
[Import("MeasureDc", typeof(IMeasureHW))]
IMeasureHW hardware { get; set; }
My importing is carried out like this:
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 am guessing the XML serialization above and using the Type
information as I do would definitely mean the import would be null so implying my thought patterns for the design are in error.
I did manage to get it to work by exporting the CompositionContainer and then after loading the XML I am able to do this:
foreach (TestRunnerBase t in testSteps)
{
_container.SatisfyImportsOnce(t);
}
But that feels a bit wrong to me, as the initial list of imported test steps isn't being used for anything apart from getting the type. So I was thinking that I should be exporting the data as MEF parts and then independently exporting the handlers, then somehow when I read in my list of data from the XML I ask for a handler from the list? If that makes sense?
I couldn't work out how you would tie them together in this way as the MEF composition is all handled in my App.xaml.cs
and the test steps are in a view model elsewhere. I was thinking something along the lines of using metadata to tie data to a handler, and then finding the corresponding handler in the imported list. Perhaps I should carry out an initial parse to build a dictionary to speed up lookups?
Is this more the way it should be done? Any help appreciated, I am already quite light in the hair department so I can't afford to lose more