4

我对 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的内部处理,并且测试步骤在其他地方的视图模型中。我正在考虑使用元数据将数据绑定到处理程序,然后在导入列表中找到相应的处理程序。也许我应该进行初始解析以构建字典以加快查找速度?

这是更应该这样做的方式吗?任何帮助表示赞赏,我在头发部门已经很轻了,所以我不能失去更多

4

1 回答 1

0

Please correct me if I'm wrong - It seems as though you could achieve your goal by chaining imports: innermost being your TestRunner collection, then the hardware classes, 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; }
    }
}
于 2013-08-18T01:35:07.843 回答