仅在定义了导出时才会发现MEF部件

时间:2014-02-26 15:22:35

标签: .net wpf mef composition

我目前正在尝试用MEF构建一个简单的概念证明,但我无法让它工作。我的解决方案中有三个项目:

  • 一个可移植的类库,它定义了一个简单的类(我们在这里简单地称它为Component)。
  • 一个.NET库,它定义一个派生自Button的类,并声明一个标有Component属性的Import类型的属性:

    public class ComponentButton : Button
    {
        [Import]
        public Component Component { get; set; }
    }
    
  • 一个WPF应用程序,其MainWindow具有ComponentButton类型的属性(标记为Export),在构造函数中初始化。然后我想使用MEF将此组件分配给窗口中出现的所有按钮(目前只有一个在XAML中定义):

    [Export]
    public Component Component { get; private set; }
    
    public MainWindow()
    {
        InitializeComponent();
    
        this.Component = new Component();
    
        var container = new CompositionContainer(new DirectoryCatalog(".", "*"));
    
        try
        {
            container.ComposeParts(this);
        }
        catch (CompositionException compositionException)
        {
            Debugger.Break();
        }
    }
    

然而,这不起作用。不会抛出异常,但组件未分配给按钮。当我查看调试器中的目录时,我可以看到,虽然所有程序集都已加载并且它找到了ExportDefinition,但它找不到导入定义。但真正令我困惑的是,当我向按钮添加导出时,它突然检测到按钮的导出和导入:

[Export]
public string Dummy { get; set; }

但即便如此,它仍然没有将组件分配给按钮。发生了什么事?

1 个答案:

答案 0 :(得分:1)

未设置按钮的属性,因为按钮是由WPF(通过InitializeComponent调用)创建的,而不是由MEF创建的。从理论上讲,你可以浏览可视树并为每个对象调用container.SatisfyImportsOnce(obj),但这对于表现性能来说是一件可怕的事情。

一种解决方案是像往常一样使用绑定设置属性。但是,按钮可以执行自组合。你必须以某种方式暴露容器(例如通过静态属性)并在构造函数中自己调用SatisfyImportsOnce按钮:

Global.MyCompositionContainer.SatisfyImportsOnce(this);

This question也可能会有所帮助。