简单的注入器和内部构造函数 [英] Simple injector and internal constructors

查看:93
本文介绍了简单的注入器和内部构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个小型类库,并为我的DI使用Simple Injector. 类库有一个访问点(我猜是某种服务),它是public,它有一些internal服务和存储库.

I am working on a small class library and using Simple Injector for my DI. The class library has an access point (some sort of a service I guess) which is public and it has some internal services and repositories.

我看到Simple Injector不支持内部构造函数的构造函数注入. 例如,我的产品服务如下:

I saw that Simple Injector does not support constructor injection with internal constructors. For example, my product service looks like:

     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());

运行代码时,出现以下异常:

When I run the code, I get the following exception:

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

我的问题:

1)是否有特定原因导致注入内部类在体系结构/设计方面不起作用?

1) Is there a specific reason that injecting internal classes doesn't work in terms of architecture/design?

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

2) How is this behavior (using dependency injection with classes that should not be public) achieved and is it desired?

推荐答案

简单注入器尝试为您提供合理的默认值.默认情况下,由于具有多个构造函数是一种反模式.默认情况下,Simple Injector仅注入公共构造函数,因为为了使Simple Injector能够安全地调用类型的构造函数,此对象必须是公共的.例如,当应用程序在(部分信任)沙箱中运行时,Simple Injector将无法调用内部构造函数,尽管可以完全信任地调用内部构造函数,但是创建此类类型的速度较慢.为了提高性能,最好使类型和构造函数保持公开状态.

Simple Injector tries to give you a sensible default. By default it is limited to auto-wiring types with a single public constructor, since having multiple constructors is an anti-pattern. Simple Injector by default only injects into public constructors, since for Simple Injector to be able to safely call a constructor of a type, this must be public. For instance, Simple Injector will not be able to call an internal constructor when the application is running in a (partial trust) sandbox, and although invoking internal constructors is possible in full trust, creating such type is slower. For performance it is best to keep the type and the constructor public.

除了这些技术约束之外,在正常情况下,组件及其构造函数将是公共的,因为您通常总是需要访问该组件的外部使用者.例如,您的单元测试项目和

Besides these technical constraints, under normal conditions components and their constructors will be public, because you would normally always have external consumers that need to access that component. Examples of such consumers are your unit test projects and your composition root project.

因此明智的默认值是一个公共构造函数",但是类型本身不必是公共的,尽管解析内部类型会比较慢,并且可能并不总是在沙箱中工作.换句话说,当您不在沙盒(例如Silverlight或Windows Phone)中运行时,简单注入器将能够解析内部类型,只要它们具有单个 public 构造函数.

So the sensible default is 'one public constructor', but the type itself doesn't have to be public, although resolving internal types will be slower and might not always work in a sandbox. In other words, when you're not running in a sandbox (such as Silverlight or Windows Phone), Simple Injector will be able to resolve internal types, as long as they have a single public constructor.

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

But if you really need or want your constructors to be internal, the constructor resolution behavior can be overridden by implementing and registering a custom IConstructorResolutionBehavior. Here's an example:

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);
    }
}

此自定义构造函数解析行为可以按如下方式注册:

This custom constructor resolution behavior can be registered as follows:

var container = new Container();

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

// Normal registrations here

这篇关于简单的注入器和内部构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆