如何通过MEF将数据传递到外部程序集用户控件

时间:2015-06-08 13:34:27

标签: wpf mvvm user-controls wpf-controls mef

我是MEF的初学者。根据我的要求,我必须根据插件的选择显示多个插件UI。为此,我必须将插件相关数据传递给外部插件UserControl。

MovieTitle | Country   | # of theatres
           |           |
Movie 1    | Country A | 5
           |           | 5
           |           | 5
           |           | 5
           |           | 5
 ....      | ...       | ...

以下代码用于从主应用程序初始化外部UI

[InheritedExport(typeof(IConnect))]

public interface IConnect{}

...

[ImportMany(typeof(IConnect))]

public IEnumerable<Lazy<IConnect>> Plugins;

//这里我必须将所需的数据传递给usercontrol。怎么做?

var catalog = new DirectoryCatalog(@"C:\TestDll\");

var container = new CompositionContainer(catalog);

container.ComposeParts(this);

var childControl = SelectedPlugin as UserControl;

请您建议一种将数据传递给外部用户控件的方法

1 个答案:

答案 0 :(得分:0)

我们在这里工作的整个团队已经使用MEF多年了,而且我对它的工作方式非常熟悉。

要让所有内容自动启动,首先要做的是确保主应用程序与外部用户控件之间共享 通用MEF容器 组装

如果您没有共同的MEF容器,那么您的MEF导入的类将永远无法与主机应用程序通信,因为它们将位于单独的MEF Universe中。

一旦你有一个普通的容器,你想从容器中引导一个类的任何地方,你可以使用这样的东西:

var test = MefContainer.GetExportedValue<ITest>();
test.Run();

Q值。如何将MEF添加到我的项目中?

一个。使用NuGet,搜索&#34; microsoft composition&#34;,并添加MEF 2.

Q值。那么我们如何创建这个共享的MEF容器呢?

一个。如下:

  • 按照From Zero to Proficient with MEF等教程进行操作。
  • 创建一个在导入的控件和主机应用程序之间共享的类库。
  • 在此类库中,创建一个名为MefContainer的单例类。这意味着任何想要从MEF容器中获取内容的人都可以引用此单例来获取MEF容器。 MEF容器包含来自我们要扫描的目录中所有自动发现的程序集的类。

Q值。如何与用户控件进行通信?

一个。将此类添加到共享类库:

public interface ITest
{
    string SharedValue { get; set; }
}

[Export(typeof(ITest))]
public class Test : ITest
{
    [ImportingConstructor]
    public Test()
    {

    }

    public string SharedValue { get; set; }
}

现在,主机应用程序和用户控件都可以从MEF容器中获取同一类的实例:

var test = MefContainer.GetExportedValue<ITest>();
var result = test.SharedValue;

默认情况下,从MEF容器中获取的类是单例,除非我们明确说明我们需要非共享类。

Q值。如何添加Reactive Extensions(RX)?

拥有共享值的类是可以的。但如果一个组件可以关闭事件,那么它会更好,而任何其他组件都可以监听此事件。

为此,请使用NuGet将RX添加到您的项目中(搜索&#34;反应式扩展&#34;添加&#34; Reactive Extensions - 主库&#34;)。

在您的共享班级中添加Subject

private Subject<string> MyEvent { get; set; }

现在,如果你有对这个共享类的MEF引用,你可以发送一个事件:

var t = MefContainer.GetExportedValue<ITest>();
t.MyEvent.OnNext("hello");

并且,任何其他类都可以订阅这些事件:

var t = MefContainer.GetExportedValue<ITest>();
t.MyEvent.Subscribe(
    o =>
    {
        Console.Write(o);
    });

如果代码已在MEF组合容器中运行,则无需使用MefContainer来获取容器。您只需使用构造函数MEF导入共享通信类:

public interface IClassRunningInContainer
{
}

[Export(typeof(IClassRunningInContainer))]
public class ClassRunningInContainer : IClassRunningInContainer
{
    [ImportingConstructor]
    public ClassRunningInContainer(ITest t)
    {
        t.OnNext("Hello, world!");
    }
}

最终笔记

不要错误地使用MEF作为一般依赖注入(DI)解决方案。由于MEF没有内置诊断级别来查明是否出现问题,因此与专用依赖注入解决方案(如Unity)相比,您将遇到障碍。

理想的模式是使用MEF导入整个装配体,然后使用Unity作为日常DI容器。