UnityContainer和内部构造函数

我有一个内部构造函数的类,并希望从Unity(2.0)解析它。

public class MyClass { internal MyClass(IService service) { } } 

然后我在做

 _container.Resolve(); 

当我这样做时,我有一个例外

 Exception is: InvalidOperationException - The type MyClass cannot be constructed. 

IService已注册,唯一的问题是构造函数是内部的。 我真的希望这个类是公开的,但我希望它只能通过工厂创建(我实际上是在调用container.Resolve() )。

有没有办法让Unity看到内部构造函数? 像InternalsVisibleTo或者什么?

我挖了一些关于如何为此目的扩展Unity的内容,并找到了一些有趣的信息。

首先,Unity似乎通过内部解析IConstructorSelectorPolicy来选择使用哪个构造IConstructorSelectorPolicy 。 Unity中包含的是public abstract class ConstructorSelectorPolicyBase ,其中包含以下gem:

 ///  /// Choose the constructor to call for the given type. ///  /// Current build context /// The  to add any /// generated resolver objects into. /// The chosen constructor. public SelectedConstructor SelectConstructor(IBuilderContext context, IPolicyList resolverPolicyDestination) { Type typeToConstruct = context.BuildKey.Type; ConstructorInfo ctor = FindInjectionConstructor(typeToConstruct) ?? FindLongestConstructor(typeToConstruct); if (ctor != null) { return CreateSelectedConstructor(context, resolverPolicyDestination, ctor); } return null; } 

FindInjectionConstructor和company是这个类中的private static方法,最终最终调用Type.GetConstructors (没有参数的重载,只返回public构造函数)。 这告诉我,如果你可以安排Unity使用你自己的构造函数选择器策略,它可以选择任何构造函数,那你就是金。

有关如何制作和使用自己的容器扩展的良好文档 ,所以我想你很可能创建自己的CustomConstructorSelectorPolicy ,它包含DefaultUnityConstructorSelectorPolicy的相关部分(它派生自抽象基类,除非你注册其他东西,否则是默认的)和ConstructorSelectorPolicyBase (直接从这个导出可能不会很好,因为关键方法不是virtual ,但你可以重用代码)。

因此,我认为这是可行的适度的麻烦,但从工程的角度来看,最终的结果将是非常“纯粹的”。

Unity只会查看公共构造函数,因此您需要将此构造函数设置为public。

我真的希望这个课程公开,但我希望它只能通过工厂创建

在这种情况下,创建一个工厂:

 public class MyClassFactory : IMyClassFactory { private readonly IService service; public MyClassFactory(IService service) { this.service = service; } MyClass IMyClassFactory.CreateNew() { return new MyClass(this.service); } } 

并注册:

 _container.Register(); 

并解决:

 _container.Resolve().CreateNew(); 

您还可以使用Unity的InjectionFactory

 container.Register(new InjectionFactory(c => { return new MyClass(c.Resolve()); })); 

为此,保存此代码的程序集应该能够看到包含MyClass的程序集的内部。 换句话说, MyClass程序集应标记为InternalsVisibleTo

还有以下几点:

 public static class MyClassFactory { public static MyClass CreateNew(IService service) { return new MyClass(service); } } container.Register(new InjectionFactory(c => { return MyClassFactory.Create(c.Resolve()); })); 

虽然您不必将构造函数公开,但这是混淆代码的好方法:-)

只需使类内部和构造函数公开…

  1. 界面公开
  2. 内部类
  3. 类public的构造函数。

可能有一些变通方法/黑客可以让你用Unity 9I做这个,不知道是否有),但一般来说如果你想让一个类由Unity(或任何IOC容器)管理,它需要公开与公共构造函数。

一个选项可能是创建一个抽象工厂,创建具有公共构造函数的类,并将类的构造函数保持在内部。 不利的一面是你的工厂将由Unity管理,但你的class级本身不会。