使用ImportingConstructorAttribute

can*_*xss 1 wpf mef

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

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

提前致谢

Wim*_*nen 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
   {
   }
Run Code Online (Sandbox Code Playgroud)

编辑以回应评论:我假设"由我们初始化而不是共享的"你的意思是你想要手动实例化一个非属性的非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
   {
   }
Run Code Online (Sandbox Code Playgroud)

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

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

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

现在回答你的问题; 如果您只是想强制MEF创建依赖项的多个实例,那么您只需要将导入属性a [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)
      {
      }
   }
Run Code Online (Sandbox Code Playgroud)

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