2014-02-11 34 views
2

我正在研究一个小型类库并使用简单注射器作为我的DI。 类库有一个接入点(我猜想某种服务),它是public,它有一些internal服务和存储库。简单的注射器和内部构造函数

我看到Simple Injector不支持带内部构造函数的构造函数注入。 例如,我的产品服务是这样的:

 internal class ProductService : IProductService 
     { 
     private IProductRepository _productRepository; 

     internal ProductService(IProductRepository repository) 
     { 
      if (repository == null) throw new ArgumentNullException("repository"); 

      _productRepository = repository; 
     } 

     } 

而且我的设置:

container.Register<IProductService, ProductService>(); 
container.Register<IProductRepository>(() => new ProductRepository()); 

当我运行代码,我得到以下异常:

For the container to be able to create ProductService, it should contain exactly one public constructor, but it has 0. 

我的问题:

1)是否有一个特定的原因,注入内部类不起作用建筑/设计术语?

2)这种行为(使用依赖注入与不应该公开的类)是如何实现的并且是它的期望?

+0

的原因是什么这些类是内部的,而不是公众:

public class InternalConstructorResolutionBehavior : IConstructorResolutionBehavior { private IConstructorResolutionBehavior original; public InternalConstructorResolutionBehavior(Container container) { this.original = container.Options.ConstructorResolutionBehavior; } public ConstructorInfo GetConstructor(Type serviceType, Type implementationType) { if (!implementationType.GetConstructors().Any()) { var internalCtors = implementationType.GetConstructors( BindingFlags.Instance | BindingFlags.NonPublic) .Where(c => !c.IsPrivate) .ToArray(); if (internalCtors.Length == 1) return internalCtors.First(); } return this.original.GetConstructor(serviceType, implementationType); } } 

这个自定义构造函数解析行为可以如下注册? – Steven

回答

3

简单的喷油器试图给你一个合理的默认值。默认情况下,它仅限于使用单个公共构造函数的自动布线类型,因为有multiple constructors is an anti-pattern。 Simple Injector默认只注入公共构造函数,因为对于Simple Injector来说,能够安全地调用一个类型的构造函数,这必须是公共的。例如,当应用程序在(部分信任)沙箱中运行时,简单注入器将无法调用内部构造函数,尽管可以完全信任地调用内部构造函数,但创建此类型会更慢。为了性能,最好将类型和构造函数公开。

除了这些技术限制,在正常情况下,组件及其构造函数将公开,因为通常情况下,您通常会有需要访问该组件的外部使用者。这些消费者的例子是你的单元测试项目和你的composition root project

因此,合理的默认值是'一个公共构造函数',但类型本身不必是公共的,尽管解析内部类型会更慢,并且可能无法在沙箱中始终工作。换句话说,当你没有在沙箱中运行时(比如Silverlight或者Windows Phone),Simple Injector将能够解析内部类型,只要它们有一个公共构造函数。

但是,如果您确实需要或希望您的构造函数为内部构造函数解析行为,则可以通过实施和注册自定义的IConstructorResolutionBehavior来覆盖构造函数解析行为。这里有一个例子:

var container = new Container(); 

container.Options.ConstructorResolutionBehavior = 
    InternalConstructorResolutionBehavior(container); 

// Normal registrations here 
+1

非常好,谢谢你的解释!我将公开我的构造函数(并同时保留一些内部类)。 – sTodorov