代码之家  ›  专栏  ›  技术社区  ›  Daniel Sklenitzka

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

  •  2
  • Daniel Sklenitzka  · 技术社区  · 11 年前

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

    • 一个可移植的类库,它定义了一个简单的类(让我们称之为 Component 此处)。
    • 一个.NET库,它定义从Button派生的类,并声明类型为的属性 组成部分 其标记有 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 回复  |  直到 11 年前
        1
  •  1
  •   Community CDub    7 年前

    没有设置按钮的财产,因为按钮是由WPF创建的(通过 InitializeComponent 呼叫)而不是MEF。理论上,你可以穿过可视化树并调用 container.SatisfyImportsOnce(obj) 对于每一个对象,但从性能角度来说,这将是一件可怕的事情。

    一种解决方案是像往常一样使用绑定设置属性。但是,可以让按钮执行自动合成。您必须以某种方式(例如通过静态属性)公开容器,并调用按钮 SatisfyImportsOnce 在构造函数中对其自身:

    Global.MyCompositionContainer.SatisfyImportsOnce(this);
    

    This question 也许也会有所帮助。