Dependency Injection with Non-Classes

2019-05-29 03:30发布

I am somewhat new to Dependency Injection. I have set it up for some classes that pass in their dependencies as parameters in the constructor, but I have some constructors that take primitives like String or boolean. Obviously these need to be removed from the constructor if I am to use Dependency Injection for that class.

For a case like this, what is a "best" practice? Make the constructor just take the dependencies and provide a setter method for all of the primitives that the class requires?

3条回答
来,给爷笑一个
2楼-- · 2019-05-29 04:15

My observation is that in most cases, classes that have a constructor that takes both dependencies and primitives, break the Single Responsibility Principle or at least result in a design that is less clean, which leads to container configurations that are more fragile and harder to understand.

In most (if not all) cases, those primitives are configuration values, such as connection strings, debug options, and such.

There are a few ways you can change your design to solve this:

  1. In the case you are breaking the SRP, extract the code into its own type. Take for instance this example where the NotifyCustomerHandler takes an string notificationServiceUrl, while that string should have been encapsulated into some sort of NotificationService.
  2. Another option is to extract the configuration values of a type into its own type. In the case of the NotifyCustomerHandler, it could take a dependency on an INotifyCustomerHandlerConfiguration. In the past I used to have a single IMyApplicationConfiguration interface, with all configuration values the application needed, but I came to the conclusion that this is a bad idea. This breaks the Interface Segregation Principle and your unit tests will start to suffer in terms of readability and maintainability.
  3. When you're not breaking the SRP and injecting a configuration object isn't practical (when you have a single primitive or getting too many configuration interfaces, or you just don't like that option), you can change these constructor arguments to public properties. This will allow you (with most containers) to register a delegate that will configure the instance after creation, in a way the compiler can verify this for you.
查看更多
疯言疯语
3楼-- · 2019-05-29 04:20

Class should take whatever dependencies it needs, in order to perform its function. Both other services it delegates some tasks to, as well as primitive dependencies (which are usually some configuration values).

Any non-trivial container will cater for this scenario and allow you to do this. Here's for example how Castle Windsor does it.

查看更多
贼婆χ
4楼-- · 2019-05-29 04:26

Obviously these need to be removed from the constructor if I am to use Dependency Injection for that class

No, not "Obviously". You can keep these parameters in as well as have the injected dependencies.

If the class requires these parameters for proper initialization, they need to be part of the constructor.

查看更多
登录 后发表回答