Search code examples
c#dependency-injectionioc-container

Dependency Injection - When to use property injection


I've a class which have a constructor like this:

    private string _someString;
    private ObjectA _objectA;
    private ObjectB _objectB;
    private Dictionary<Enum, long?> _dictionaryA;
    private Dictionary<Tuple<Enum,long?>, long?> _dictionaryB; 

    public SomeDiClass(string someString)
    {
        _someString = someString;

        _objectA = new ObjectA();
        _objectB = new ObjectB();

        _dictionaryA = new Dictionary<Enum, long?>();
        _dictionaryB = new Dictionary<Tuple<Enum, long?>, long?>();
    }

I want to get the dependency creation out of this constructor. In a first step I would move the ObjectA and B dependency to the constructors parameters to inject them via constructor injection. I would like to use a IoC container for this purpose, that's where I stuck at the moment. The question is what to to with someString and the dictionaries. I need to inject them to the class, because the content of the dictionaries will be an important part of unit tests. Would it be a good idea to inject the string and the dictionaries via property injection (I don't need them in other classes), so I would end up with something like this?:

    private ObjectA _objectA;
    private ObjectB _objectB;

    public string SomeString { get; set; }
    public Dictionary<Enum, long?> DictionaryA { get; set; }
    public Dictionary<Tuple<Enum, long?>, long?> DictionaryB { get; set; }

    public SomeDiClass(ObjectA objectA, ObjectB objectB)
    {
        _objectA = objectA;
        _objectB = objectB;
    }

Is there a best practice to solve something like this?


Solution

  • Dependency Injection is not an end goal, but a solution to a particular set of problems. For instance, Dependency Injection makes it easy to replace abstractions for unit testing and makes your application more flexible, since you can swap, decorate and intercept dependencies without having to change the consuming classes. A good introduction to Dependency Injection can be found in this freely available chapter 1 of the book Dependency Injection Principles, Practices, and Patterns (DIPP&P), which I coauthored.

    That doesn't mean that you should inject every dependency a class has, since it must help you in making the class more testable and the system more maintainable. So you have to ask yourself whether it helps from a testing perspective to inject those dictionaries from the outside or if it helps to make your application more flexible. To get a good grasp on what to inject—and what not—you should learn about the concepts of Volatile and Stable Dependencies, which can be read in section 1.3 of chapter 1 of DIPP&P.

    Whether it helps from a testing or maintainability perspective, is a question that is hard to answer, because your question doesn't have enough detail. But here are some pointers:

    The only things you typically want to inject into a class are services and configuration values.

    • A service is some contract/abstraction/interface that provides 'a service.' This typically means that the service will do something on your behalf, such as calculate prices, communicate to the database, cache values, return the system's time, or format your hard drive :)

    • A configuration value is what it is; just a value. But you need to inject it—it can't be hard coded into the class, and you don't want the class to fetch the value itself from the ConfigurationManager, for instance, because that would create a hidden dependency (on the Configurationmanager) and this would make the class harder to test.

    Other things, such as primitives, messages, DTOs, collection types and entities, and anything else that doesn't provide any service (business logic) and isn't in the way of unit testing, doesn't have to be abstracted and, therefore, doesn't have to be injected (and in fact shouldn't be injected through the constructor or property). In your case the dictionaries can become part of the internal state of the SomeDiClass class, not a service your class depends on.

    If, on the other hand, those dictionaries are reused by other services, those dictionaries will have to be injected. But you hardly ever want to inject such dictionary itself directly, since the dictionary itself is no service. Instead you need to create an abstraction around them; something that hides the details of that dictionary and provides the application with a service around it.

    Besides Constructor Injection and Property Injection, there is a third injection pattern, namely Method Injection. Where dependencies are injected using Constructor Injection and Property Injection by your application's Composition Root, it is application code itself that passes dependencies on through Method Injection. When it comes to choosing the right injection pattern, the easy answer is that within your Composition Root, Constructor Injection is the right answer in almost all of the cases. Complete applications can be designed using solely Constructor Injection. Property Injection is hardly ever needed. Method Injection, on the other hand is useful in some cases. To understand when you would want to use it, read this article.