2013-02-12 28 views
4

我对MEF有点困惑,我以为我已经开始理解它,但看起来我并不在那里。如何从MEF导入创建新对象

所以,我有一个XML测试步骤的列表,我想读入它的想法是主应用程序在运行时不知道有关类型的任何信息。

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

所以我有一个静态的“结果”类的基类型,让我将信息保存到步骤(该Output属性在上面的XML)之间通过。这里的测试处理程序由MEF导出,我在运行时读取它们,然后将Type传入XML序列化程序以创建处理程序列表。这一切都有效,我得到一个测试跑步者名单。我在这里为每种类型导出DataTemplate,所以当我使用内容控件时,它知道如何绘制自己。所有的一切似乎都很好,但是我认为我的思维过程出了问题。

一个问题是,我现在想要将导入的处理程序绑定到某些硬件。处理例程的硬件旨在通过更进一步MEF进口

所以与接口这样的处理:

public interface IMeasureHW 
{ 
    double Measure(); 
} 

然后使用此:

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

然后在我的测试处理器的一个我已经这样做了:

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

我的导入是这样进行的:

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(); 
} 

不过,我猜上面的XML序列化和使用Type信息为我做肯定将意味着进口将是空,因此这意味着我的思维模式的设计是错误的。

我还是设法得到它通过导出CompositionContainer中工作,然后加载XML之后,我能够做到这一点:

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

但是,这感觉有点不对劲对我来说,作为初始列表导入的测试步骤除了获取类型之外不用于任何其他任何操作。所以我在想,我应该将数据导出为MEF部分,然后独立导出处理程序,然后以某种方式从XML读取我的数据列表时,我要求列表中的处理程序?如果这有道理?

我无法弄清楚如何以这种方式将它们绑定在一起,因为MEF的组成都是在我的App.xaml.cs中处理的,并且测试步骤在别处的视图模型中。我在考虑使用元数据将数据绑定到处理程序,然后在导入列表中找到相应的处理程序。也许我应该进行初步解析来构建一本字典以加快查找速度?

这是更应该怎么办?任何帮助表示赞赏,我已经在头发部门很轻,所以我不能失去更多

+1

你创建通过MEF容器的测试操作?你能发布执行容器和目录创建的代码吗? – Dennis 2013-02-12 12:18:12

+0

我做了一些错误,事实证明,初始导入不是null。所以我已经更新了相应的问题,因为它实际上与我的想法不同。 – Firedragon 2013-02-12 12:44:05

+0

您看过MEF的导出元数据吗? http://mef.codeplex.com/wikipage?title=Exports%20and%20Metadata – 2013-02-12 22:11:36

回答

0

如果我错了,请纠正我 - 好像你可以通过链接进口实现你的目标:innermost being你的TestRunner集合,然后是硬件类,最后是内容控制。

在下面这些例子都是Class2 : MySubInterfaceClass1 : MyInterface,并分别Program

/////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; } 
    } 
}