Dependency Injection (DI) with Generics (or maybe not)?

[I am not the post boy for doing DI; I’m on good record for seeming to be against it, but I was reading an article on DI (yes, I read up on a number of things that run counter to my beliefs... I’m a thinker, so I think debate is a good thing and learning about the stuff outside your normal realm is a way to better yourself).]

I don’t think I’ve ever seen anyone talk about this and I did it recently. Basically you create a class like this:

   1: public class MyClassWithADependency<T> : SomeBaseClass where T:ISomeInterface,new()
   2: {
   3:     T _dependency;
   4:     public MyClassWithADependency()
   5:     {
   6:         _dependency = new T();
   7:  
   8:         // Use _dependency in the rest of your code
   9:     }
  10: }

If you are a TDD guy (or are familiar with unit testing), you have just enabled a whole scenario of things. Mind you have I have no idea how well this works with an IOC library (Ask Jeremy Miller or one of those guys), but the idea really has some merit for me (although I won’t be doing this everywhere).

In my case I am preparing for an expansion on a library I just wrote for work. It has something to do with reading Excel documents with FarPoint Spread and importing the data... what quickly came to light is that there will very quickly be a number of new requirements for our app that use Excel imports (so new data, so parsing mechanisms). BTW, our mechanism uses FarPoint to generate an Excel export file that is used by our users for data entry.

Anyway, I wanted to keep much of my parsing routines, but merge in new data structures. Injection via generics works great. I was even able to derive a new class based on a specific generic like this:

   1: public class MyNewClass : MyClassWithADependency<ClassThatImplementsISomeInterface>
   2: {
   3:     public MyNewClass() : base()
   4:     {
   5:     }
   6:     // Rest of your definition goes here
   7: }

Testing??

Since I’m not a TDD guy nor do I use Automated Test tools like MbUnit on a heavy basis, I will defer on this one. I will rely on someone like Chad or one of my regular readers to do it for me.

[Of course this example may be totally "whack" in which case tell me, please...]

Print | posted on Thursday, September 18, 2008 11:39 AM

Feedback

# re: Dependency Injection (DI) with Generics?

left by Derik Whittaker at 9/18/2008 5:08 PM Gravatar
This is about the worst implementation (wanna be implementation) of DI I have ever seen.

You are making a huge assumption that you will only ever need to inject 1 dependancy. WRONG.

On the up side, you just invented a new form of DI called Generic Injection. Now we have 3 types of injection (constructor, setter and generic).

I would not suggest you use this pattern in real life.

# re: Dependency Injection (DI) with Generics?

left by Rob T at 9/18/2008 5:30 PM Gravatar
Without being as beligerant as Mr. Whittaker here, I'll talk about a few issues with ragards to this kidn of pattern.

First, it's usally the case that when something varies only by type, that's a sign that type templating (generics) should come into play. But there are some caveats in this particular case, which I'll get to in a bit.

Second, DI and IoC are nothing new and don't exist solely in the realm of testing. These concepts were invented long before automated unit testing became the new hip thing. If you look at a lot of software out there that have interchangeable implementations, this is actually the norm. Take the .NET crypto framework as an example. When you call DES.Create(), it's using a factory implementation to create a specific implementation of the DES algorithm (or any other cipher, take your pick, depending on the base class). That way, your application isn't stuck using a single implementation, and the Ops guys can even swap it out in production with a simple config change (the concrete type is specified in machine.config i believe).

However, when you create an entire framework where every (or nearly every) dependency is uncoupled and replaceable, you need some plumbing to do the type resolution of the hundres or thousands of dependency instantiations you might have. That plumbing will either take a giant config or allow the program to dynamically specify the type resolutions.

And this is where the generics approach kinda fizzles. At some point, someone is going to have to specify a concrete T. But if the app doesn't know that T is going to be until runtime, you can't really do that without resorting to hokey reflection, so it's sort of a moot point, and wouldn't offer any more than non-generics approaches that are already out there.

# re: Dependency Injection (DI) with Generics?

left by Tim Barcz at 9/18/2008 5:35 PM Gravatar
Is it possible to post an update to this article and make it highly visible. While I don't want to be too hard on you, this is really spreading some misinformation and bad practices.

Tim

# re: Dependency Injection (DI) with Generics?

left by Scott Bellware at 9/18/2008 5:49 PM Gravatar
Jay,

It isn't dependency *injection* unless you push the dependency in from the outside, which is what the pattern arrives at when doing TDD and needing to verify that the dependency was used correctly based on the logic in the class that uses the dependency.

Constructing dependencies an the using class's constructor is what dependency injection seeks to avoid. T _dependency is a dependency is a dependency, but it's an opaque dependency that can't be replaced at runtime with a fake or a simulator for testing purposes.

Let's say that T _dependency is a funds transfer service. It's easier when writing logic for the using class to use a fake funds transfer service than a real funds transfer service.

You could use configuration to swap the funds transfer service with a fake, but then you'd have to twiddle configuration between logic unit testing and end to end testing. It's simple and more direct to open up the dependency in the using class's constructor:

public MyClass(T dependency)
{
_dependency = dependency
}

In test code, you simply construct the class using the dependency that is appropriate to the kind of test:

new MyClass(new FakeDependency)

An IoC tool automates object construction by inspecting constructor arguments and providing the instances of the dependencies that are already in the IoC container:

container.AddDependencyType(typeof(FundsTransferService))

So constructing the using class is never more difficult than:

MyClass myObject = container.Build<MyClass>();

If FundsTransferService had dependencies exposed through its constructor args, and those dependencies had dependencies exposed through their constructor args, and so on, construction of MyClass would always be the same:

MyClass myObject = container.Build<MyClass>();

As long as the container is fed the System.Type of all of the dependency objects, constructing any class with dependencies is always a simple matter of asking the container for an instance of some object where the entire chain of exposed dependencies is populated.

So, test code becomes much simpler, dependencies are explicitly documented via constructor args, and production code (or production testing code) benefits from the intelligence of the IoC container and the dependency types that have been added to it.

Inversion of Control (IoC) simple means something like, "push dependencies in from the outside," and an Inversion of Control container (or "framework"), is just an automation tool for doing this stuff in production.

# re: Dependency Injection (DI) with Generics?

left by Chad Myers at 9/18/2008 5:50 PM Gravatar
@Derik: Ouch! Take it easy on Jay, he's learning-out-loud which can lead to mistakes (publicly). This is a teachable moment :)

@Jay: I would not call this Dependency Injection per se. Well, at least not for MyNewClass. MyNewClass has a static dependency on ClassThatImplementsISomeInterface and there's no injection going on and therefore would not be as testable.

However, MyClassWithADependency<T> does have a measure of dependency injection (or rather, dependency transparency, it's not really being injected).

This assumes that there is logic in the MyClassWithADepdencny<T> that needs tested (and if not, why does MyClassWithADependency<T> exist in the first place ;) )

You could do a PartialMock of MyClassWithADependency<T> using Rhino Mocks and use a Test Double implementation of ISomeInterface to set up your interaction testing.

However, you really haven't made your life any easier by doing this. It depends what the problem is and what other options are or are not available to you to solve it.

Generally, I would not recommend this approach and, instead, prefer Constructor and possibly Setter/Property injection. It's just easier!

# re: Dependency Injection (DI) with Generics?

left by Chad Myers at 9/18/2008 5:51 PM Gravatar
@Jay: Or.... what Scott said :)

# re: Dependency Injection (DI) with Generics?

left by Derik Whittaker at 9/18/2008 6:01 PM Gravatar
Jay,

I came back to better explain myself and my thoughts because it dawned on me that my comments were not helpful, but others have done a great job of explaining the failings of this post.

Sorry for the 'mean spirited' comment.

# re: Dependency Injection (DI) with Generics (or maybe not)?

left by Jay Kimble at 9/18/2008 8:37 PM Gravatar
Guys,

Much of what I'm up to is experimentation. The idea that I stuck the "?" was what should have been the tip off that I was unsure.

Rob kind of stated why I am using this, and I guess I saw that it was easily mockable that made me think... hmmm... this might be useful to you guys.

I guess not...

Jay

PS... I updated the title of the post to reflect that it's not Dependency Injection...

# re: Dependency Injection (DI) with Generics (or maybe not)?

left by Jay Kimble at 9/18/2008 8:44 PM Gravatar
a couple more things... Derek your reaction is exactly why I move away from you guys. Something sounds slightly off and it sounds like ti might be talking about your arena and you jump on it with your big sticks and club the poor soul to death (I'm serious). You are forgiven, because... well... I probably would have done the same... I know how I react sometimes (and I may have done so to you before)
--------
As to Chad's comments... I prefer experimentor to "learning." The truth is that I have thrown out some of what you guys are about already, but I don't want to throw out the baby with the bathwater... there are some really good things you guys have that I would like to figure out how leverage (without taking the whole package)... Sorry... that's where I am.

(Seeing this reaction, Chad, I will never post that SpDD post on my tests from the other day)...
--------
Scott B., Thanks for being gentle....

# re: Dependency Injection (DI) with Generics (or maybe not)?

left by chrissie1 at 9/19/2008 7:39 AM Gravatar
I agree with Jay. Experimenting is good and helps you learn. It is not only important to know the does but most certainly the don'ts. And not taking everything for granted is the only way to evolve as a person and as a professional.

Anyway most reactions were very positive and nobody died.

# re: Dependency Injection (DI) with Generics (or maybe not)?

left by James Hart at 9/19/2008 11:53 AM Gravatar
Astonishing reactions.

I think your mistake may have been to suggest this was a Dependency Injection strategy, not simply a strategy for injecting a dependency. It's those Capital Letter terms that cause the angry posts.

Because clearly, the originally stated MyClassWithADependency<T> class does provide a mechanism for specifying at the point the class is used what implementation of a particular dependency it should employ.

Alright, so it's not as flexible as it might be. It requires the injected class to support parameterless construction. It accomplishes little that's not already accomplished by simply writing this (constructor-injectable) class:

public class MyClassWithADependency : SomeBaseClass
{
ISomeInterface _dependency;
public MyClassWithADependency(ISomeInterface dependency)
{
_dependency = dependency;

}
}

This version requires the calling code to supply the dependency (or allows an IoC container to do it), which lets you relax the parameterless constructor restriction. But they're not hugely different.

Jay's generic class simply enforces a policy about who's responsible for instantiating the dependency (that might be desirable in some circumstances, since it's clear who's going to clean it up), and also exposes the implementing dependency type as part of the runtime type of the object - which also might be useful in some circumstances.

For goodness' sake, it's just a generic class with a constraint on it; the point is valid that such a class can be used to externalise the choice of a dependency implementation from the implementation of the dependent class. Not everything has to use an IoC container, not everything has to use an approved Dependency Injection pattern.

It's just a way of moving implementation decisions and dependencies around your codebase. It's all good. Chill.

# re: Dependency Injection (DI) with Generics (or maybe not)?

left by Scott Bellware at 9/19/2008 2:53 PM Gravatar
James,

Since the varying of the dependency can only be done at compile time, why make it so abstractly-variable. The result is inevitably static rather than variable. It's only variable in source code. What value does this approach bring that pays for the tradoff that comes from making things perhaps unnecessarily abstract?
Comments have been closed on this topic.