【问题标题】:Simple injector and internal constructors简单的注入器和内部构造函数
【发布时间】:2014-03-08 22:36:45
【问题描述】:

我正在开发一个小型类库,并为我的 DI 使用 Simple Injector。 类库有一个访问点(我猜是某种服务),它是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) 这种行为(对不应该公开的类使用依赖注入)是如何实现的,是否需要?

【问题讨论】:

  • 这些类是内部类而不是公共类的原因是什么?

标签: architecture dependency-injection simple-injector


【解决方案1】:

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

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

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

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

public class InternalConstructorResolutionBehavior : IConstructorResolutionBehavior
{
    private IConstructorResolutionBehavior original;

    public InternalConstructorResolutionBehavior(Container container) {
        this.original = container.Options.ConstructorResolutionBehavior;
    }

    public ConstructorInfo GetConstructor(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(implementationType);
    }
}

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

var container = new Container();

container.Options.ConstructorResolutionBehavior = 
    new InternalConstructorResolutionBehavior(container);

// Normal registrations here

【讨论】:

  • 太好了,谢谢你的解释!我将公开我的构造函数(同时保留一些内部类)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-28
  • 1970-01-01
  • 2012-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多