简体   繁体   English

拥有2个构造函数是正确的,一个用于依赖注入,另一个用于解析注入?

[英]It's correct to have 2 constructors, one for Dependency Injection and the other one Resolving the injection?

I have 2 constructor in my class: 我班上有2个构造函数:

public class VuelingCacheWebServices : IVuelingCacheWebService
    {
        public IVuelingCache apiConnector { get; set; }

        public VuelingCacheWebServices(IVuelingCache ApiConnector)
        {
            apiConnector = ApiConnector;
        }

        public VuelingCacheWebServices()
            : this(new VuelingCache())
        { }
    }

As you can see, I have one constructor depending on IVuelingCache and a default constructor that creates an instance to pass to the first constructor. 如您所见,我有一个构造函数,具体取决于IVuelingCache和一个默认构造函数,它创建一个传递给第一个构造函数的实例。 Is it correct? 这是对的吗? in this way i get rid of the Factory class. 通过这种方式我摆脱了Factory类。

This is one way to ensure that you have a valid instance of IVuelingCache - this pattern has a name - poor man's dependency injection. 这是确保您拥有一个有效的IVuelingCache实例的IVuelingCache - 这个模式有一个名字 - 穷人的依赖注入。

Some see this as an anti-pattern, as you are hard coding the "default" implementation into your code. 有些人 认为 是一种反模式,因为你很难将“默认”实现编码到你的代码中。

There is some debate as to that pattern being a good idea: 关于这种模式是一个好主意,存在一些争论:

http://lostechies.com/chadmyers/2009/07/14/just-say-no-to-poor-man-s-dependency-injection/ http://lostechies.com/chadmyers/2009/07/14/just-say-no-to-poor-man-s-dependency-injection/

In my opinion, if you have a good default that isn't a logically external dependency, then you should provide that default. 在我看来,如果你有一个不是逻辑上的外部依赖的良好默认值 ,那么你应该提供该默认值。 If your "default" really shouldn't be a default, or would couple pieces that are too far from each other too strongly, then do not use that pattern. 如果您的“默认”确实不应该是默认值,或者会过于强烈地将彼此相距太远的部分联系起来,那么请不要使用该模式。

You couple your code by doing this, so really think long and hard about whether it will be used as a convenience default for locally available default implementations, or if you're really just using this as a crutch, and causing inappropriately strong coupled dependencies. 你通过这样做来结合你的代码,所以真的要长时间地考虑它是​​否会被用作本地可用的默认实现的便利默认值,或者如果你真的只是将它用作拐杖,并导致不适当的强耦合依赖。

Also, many people advocate using constructor injection only for required dependencies, and using property injection for optional dependencies. 此外,许多人提倡仅对所需的依赖项使用构造函数注入,并对可选的依赖项使用属性注入。 When you use the poor-man's DI pattern, you are making an optional (or defaultable) dependency. 当你使用穷人的DI模式时,你会产生一个可选(或默认)的依赖。 You might want to consider using property injection for these optional-dependency cases, as that is the pattern many people expect. 您可能需要考虑对这些可选依赖性情况使用属性注入,因为这是许多人期望的模式。

不,这不是一个好主意,因为你的班级将成为有关IVuelingCachenew VuelingCache() )实现的知识。

There are a few problems with your approach: 您的方法存在一些问题:

  1. It makes your code less understandable. 它使您的代码不易理解。 Not only is it more code to write, but it is harder to see what dependencies the class takes. 不仅要编写更多代码,而且更难以看到类所依赖的依赖项。 When you have one single constructor, it is immediately clear what its dependencies are. 当你有一个构造函数时,它立即清楚它的依赖是什么。
  2. It makes the class depend on concrete instances. 它使类依赖于具体实例。 This makes it hard to separate abstraction and implementation and could be bad from an architectural point of view. 这使得很难将抽象和实现分开,从架构的角度来看可能很糟糕。
  3. It forces you to make changes to that class when implementations change, which is bad for maintainability. 它强制您在实现更改时对该类进行更改,这对可维护性是不利的。 Say for instance your application uses ICommandHandler<T> interfaces as abstraction to execute business commands and that your class depends on an ICommandHandler<UpdateUserCommand> and points at the concrete UpdateUserCommandHandler . 比如说你的应用程序使用ICommandHandler<T>接口作为抽象来执行业务命令,并且你的类依赖于ICommandHandler<UpdateUserCommand>并指向具体的UpdateUserCommandHandler When you later on want to wrap any ICommandHandler<T> inside a DurationLoggingCommandHandler<T> , DeadLockRetryCommandHandler` or what not, you need to go through your complete application to replace all dependencies, while otherwise it is just a matter of rewiring the configuration in the startup path of your application. 当你以后想要在DurationLoggingCommandHandler<T> ,DeadLockRetryCommandHandler`中包装任何ICommandHandler<T> ,你需要通过你的完整应用程序来替换所有依赖项,否则它只需要重新配置配置应用程序的启动路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM