Dependency Injection - When to use property injection
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 theConfigurationmanager
) 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 some 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 never 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.
You should use property injection (or setter injection) when object creation of your type is out of your control. Like aspx Page, HttpHandler, ApiController etc. For all others situations it is recommended to use constructor injection.
To resolve dependencies for aspx Page using StructureMap, i use the following approach.
First, I create a BasePage class and use StructureMap's BuildUp() method in the constructor to resolve dependencies of the derived pages. Code is given below:
public class BasePage : Page
{
public BasePage()
{
// instruct StructureMap to resolve dependencies
ObjectFactory.BuildUp(this);
}
}
public class Default : BasePage
{
public ICustomerService customerService { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
// can start using customerService
}
}
public class Login : BasePage
{
public IAuthenticationService authenticationService { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
// can start using authenticationService
}
}