Property vs. Constructor vs. Explicit Dependency Injection

Oct 6, 2008 at 6:32 PM
New to Unity and trying to get my head around it.  As I understand it, there are 3 basic ways to enable dependency injection, via a Property for a dependent object, add the dependent object to the constructor of the parent object, or explicitly call the container.Resolve method.

I'm curious about best practices for each type... are they all equivalent?

For instance, choosing to use the Constructor method over choosing to use container.Resolve primarily saves writing some code.  Are there any other reasons one would choose one of these DI methods over another?

Thx

Oct 6, 2008 at 8:53 PM
Hi Lefty,

I'll assume you are creating a component and you'd like external dependencies to be injected into your component. If you aren't creating components for consumption by other applications, then you can pretty much ignore what follows and do the injection in whatever way seems best to you.

If you use constructor injection, your component can be used by anyone who is using a container that supports constructor injection. This is the optimal approach. Make sure you don't use any attributes that are container-specific.

If you use Property (Setter) injection with Unity, then you will be using attributes to decorate the properties and your component will only be useful in applications that are using Unity.

If you explicitly use unityContainer.Resolve inside your component, then you again are creating a hard dependency on Unity.

That being said, you can resolve dependencies dynamically inside your component, in a 'container-independent' fashion, by taking advantage of the Common Service Locator interface. Make your internal references to the container of type IServiceLocator. Then you will be able to ask the container to resolve a dependency regardless of the actual container implementation, so long as there is a CSL implementation for it. See http://www.codeplex.com/CommonServiceLocator.

Ray Henry
http://initializecomponent.blogspot.com/

Oct 6, 2008 at 9:11 PM
Ray has it mostly right. If you're using Property injection, you can use attributes, but you don't have to; you can instead configure the container to specify which properties are injected either via API or config file. So no hard dependency there.

In my mind, prefer constructor injection whenever possible. It prevents coupling. If you call container.Resolve inside your component, then you need to have the container passed to you anyway. Constructor or property injection also has the advantage that you can tell just by looking at the class metadata what the dependencies are. If you're calling Resolve inside the code, the only way to find out what's being resolved (and therefore how to configure the container) is by actually digging through the code to the component.

Oct 6, 2008 at 9:56 PM
Ok, some good stuff there.

As for my usage, I am trying to prototype a large application: ASP.NET using MVP, WCF business service with DAL.  My first implementation uses Resolve<IDAL> in the business layer, to resolve which DAL is going to be used, an Entity Framework version or an ADO.NET version (that uses Data Access Application block).  I then started expanding the search through the layers, looking for other appropriate places to make use of Unity.  I came across a David Hayden example for MVP, and planned to try to work that in as well.

I see your point about using the constructor and being able to read/infer the dependencies without looking at the code.  But I am a bit confused too.  When a component takes a dependency in the constructor, it "exposes" some of the secrets of that component.  For instance, the Quickstarts have a sample where the SalesData class has a constructor:

SalesData([Dependency]Database db)

It seems a bit counterintuitive to me to let the consumer of the SalesData class even know that it requires a Database, much less open the door to be provided one within the constructor.  In some ways, to me, it seems like it works against the idea of abstraction and separation of the layers, because now, the consumer of SalesData "knows more about" the SalesData class and it becomes less of a black box.

I also see your point about the dependency on Unity (when using Resolve()) but I guess I figured that if I put effort into creating config files or reading the configuration from the database, that I was thinking that Unity was more or less a non-negotiable dependency, being used throughout the whole application and the likelihood of wanting to replace it with another DI provider later on was small.  (I should never say never, I guess)  8-)

I guess my first understanding of Unity was that it provided me a way to dynamically change the class that implements an interface.  Perhaps I am missing some additional benefits, when it is used properly.

I'd appreciate some more comments to help me fully understand Unity.... I think I'm getting closer, but not quite there yet.

Thx


Oct 6, 2008 at 10:08 PM
Yeah, I agree that having the component expose its dependencies is a bit counter-intuitive and seems to go against "abstraction". But consider that you are letting the container manager the dependencies - you will never call the constructor, so the application does not need to know about the dependencies; it's still a black box. If dependencies change later, then you update your component and the (small) bit of code that configures the container and there are no changes to the application (in theory).

And you are right, if you intend to have complete control of all your layers, then making dependencies on Unity is not so bad, but you know at some point someone is going to ask you if you can bundle up some of your functionality and let them use it as a component. Then you'll appreciate minimizing the coupling.

Ray
Oct 6, 2008 at 11:18 PM
You're basically looking at Unity as a Service Locator, which is one way to use it. Have you looked at Fowler's Dependency Injection vs. Service Locator piece? It might help clear up some of the confusion.

It is fairly well known that the DI style violates encapsulation. Yes, your consumer now knows that SalesData needs a database. (BTW, the [Dependency] attribute on the parameter is unnecessary unless you're resolving a named registration). But think about it this way - how would you write a unit test for SalesData if the dependency on Database wasn't exposed? If you're new-ing up the Database internally, you can't test that class without having a live database on the other end. And the only way to know that is by reading the internals of the code.

Exposing the dependencies this way is a great way of increasing the isolation of your units. That makes them easier to test and you often end up with a better design in the end.

Oct 7, 2008 at 3:59 PM
Ok, good, I think I'm getting it.  Now to push it a bit further.  Your point about being more testable is good.  I have not worked with coded unit tests before, but I plan to with this project.  As a result, my knowledge of test frameworks is minimal at this point, as I haven't dug into that area of things just yet.  I'd appreciate your advice on best use of constructor injectors, using another example.

The IDAL implementation I mentioned earlier has three distinct parts.

  • Adapter - this class exposes the DAL functionality to the consumer (ie. LoadCustomerById()) - it acts like a manager within the DAL
  • DataAction - this class is internal to the DAL and is used by the Adapter (adapter depends on dataaction) - this also exposes a LoadCustomerById and is responsible for the actual query execution and returns a DataTable (or another appropriate container - for the Entity Framework DAL, this would return an Entity Framework Model Customer object)
  • Mapper - also internal to the DAL, also used by the Adapter (adapter depends on Mapper) - this performs object translation to the common return type defined by the IDAL, so for this method, it would accept the DataTable and instantiate and populate a Business Entity Customer object to be returned by the Adapter (or convert the EF Model entity to a Business Entity Customer)
So in my case above, the DataAction class has a dependency on the Database class (Data Access Application Block).  Now I can add the Database class to the DataAction constructor, for use with DI.  However, this probably won't fully help me with testability will it? Since my tests would likely create an Adapter object, not a DataAction object.  If I create an Adapter object within a test, and wanted to substitute the Database for a mock database instead of a real one, what would be the best DI architecture to support that?

Should I chain everything together, where:
Adapter(DataAction da, Mapper m)
DataAction(Database d)

So Adapter depends on both and DataAction depends on Database? 

Would this allow me, in a test, to create a real Adapter and a real Mapper and a real DataAction, and sub in a mock Database?  My inexperience with the testing frameworks is glaring here. 

Also, it seems a bit of overkill to use DI for Mapper, since I don't see the need to dynamically locate that service... switching the IDAL from EF to ADO.NET makes sense, but within the ADO.NET DAL, swapping the Mapper from one to another seems unlikely.  Maybe I should remove the Mapper from the Adapter constructor?

Thoughts?