使用ImportingConstructorAttribute

时间:2010-02-04 12:23:55

标签: wpf mef

我正在尝试使用MEF和MVVM构建WPF应用程序。我正在导出我的ViewModel,但我希望我的ViewModel接受构造函数中的Model参数:我将创建一个特定的Model并将其提供给ViewModel的构造函数。我试图了解ImportingConstructorAttribute是如何工作的,似乎是拥有自定义构造函数的方法。但我无法弄清楚如何使用它。

有人可以举例说明使用ImportingConstructorAttribute吗?

提前致谢

1 个答案:

答案 0 :(得分:5)

你走了。类Test通过构造函数导入IFoo实例:

   public class Program
   {
      public static void Main(string[] args)
      {
         var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
         var container = new CompositionContainer(catalog);
         Test test = container.GetExportedValue<Test>();
      }
   }

   [Export]
   public class Test
   {
      private IFoo foo;

      [ImportingConstructor]
      public Test(IFoo foo)
      {
         this.foo = foo;
      }
   }

   public interface IFoo
   {
   }

   [Export(typeof(IFoo))]
   public class Foo : IFoo
   {
   }

编辑以回应评论:我认为“由我们初始化而不是共享”你的意思是你想要手动实例化一个非属性的非MEF类并将其注入MEF部分的依赖关系。通常你会这样做:

   public class Program
   {
      public static void Main(string[] args)
      {
         var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
         var container = new CompositionContainer(catalog);

         // create and add non-MEF instance explicitly to container
         var nonMEF = new NonMefClass();
         container.ComposeExportedValue<IFoo>("Test.foo", nonMEF);

         Test test = container.GetExportedValue<Test>();
      }
   }

   [Export]
   public class Test
   {
      private IFoo foo;

      [ImportingConstructor]
      public Test([Import("Test.foo", typeof(IFoo))] IFoo foo)
      {
         this.foo = foo;
      }
   }

   public interface IFoo
   {
   }
   public class NonMefClass : IFoo
   {
   }

使用ComposeExportedValue向容器明确添加实例的替代方法是使用属性导出。然后,您可以根据需要在属性getter中初始化非MEF对象:

   public class Bar
   {
      [Export("Test.foo", typeof(IFoo))]
      public IFoo Foo
      {
         get
         {
            return new NonMefClass();
         }
      }
   }

编辑以回应评论2 :首先警告;在MEF预览8中,ImportingConstructor和PartCreator似乎不能很好地协同工作,可能是因为PartCreator只是一个尚未经过充分测试的样本。使用属性注入导入PartCreator实例。

现在回答你的问题;如果您只是想强制MEF创建依赖项的多个实例,那么您只需要将导入属性[Import("Test.foo", typeof(IFoo), RequiredCreationPolicy=CreationPolicy.NonShared)]

如果你为每个实例完成不同的组合,那么事情就会复杂一些。您不能真正拥有单个部分(即具有MEF属性的类),并且除非您设置了多个容器,否则它将针对不同的零件实例进行不同的组合。相反,我在这种情况下所做的是创建从公共类继承的多个部分。然后,每个所需的组合有1个子类:

   public class Test
   {
      private IFoo foo;

      public Test(IFoo foo)
      {
         this.foo = foo;
      }
   }

   [Export]
   public class TestComposition1 : Test
   {   
      [ImportingConstructor]
      public Test([Import("TestComposition1.foo", typeof(IFoo))] IFoo foo)
         : base(foo)
      {
      }
   }

   [Export]
   public class TestComposition2 : Test
   {   
      [ImportingConstructor]
      public Test([Import("TestComposition2.foo", typeof(IFoo))] IFoo foo)
         : base(foo)
      {
      }
   }

这当然要求您考虑到有限数量的替代作品。如果在设计时无法枚举所需组合的数量,则需要更复杂的东西,可能涉及PartCreator和基于零件元数据的动态选择。