Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Consider:

public class CtorInjectionExample
{
    public CtorInjectionExample(ISomeRepository SomeRepositoryIn, IOtherRepository OtherRepositoryIn)
    {
        this._someRepository = SomeRepositoryIn;
        this._otherRepository = OtherRepositoryIn;
    }

    public void SomeMethod()
    {
        //use this._someRepository
    }

    public void OtherMethod()
    {
        //use this._otherRepository
    }
}

against:

public class MethodInjectionExample
{
    public MethodInjectionExample()
    {
    }

    public void SomeMethod(ISomeRepository SomeRepositoryIn)
    {
        //use SomeRepositoryIn
    }

    public void OtherMethod(IOtherRepository OtherRepositoryIn)
    {
        //use OtherRepositoryIn
    }
}

While Ctor injection makes extension difficult (any code calling the ctor will need updating when new dependencies are added), and method level injection seems to remain more encapsulated from the class level dependency and I can't find any other arguments for/against these approaches.

Is there a definitive approach to take for injection?

(N.B. I have searched for information on this and tried to make this question objective.)

share|improve this question
3  
If your classes are cohesive, then many different methods would be using the same fields. This should give you the answer you seek... –  Oded Apr 3 '12 at 13:08
    
@Oded Good point, cohesion would heavily influence the decision. If a class is, say, collections of helper methods that each have different dependencies (seemingly not cohesive, but logically similar) and another is highly cohesive, they should each use the most beneficial approach. However, this would cause inconsistency across a solution. –  StuperUser Apr 3 '12 at 13:14
    
Relevant for the examples I've given: en.wikipedia.org/wiki/False_dilemma –  StuperUser Apr 3 '12 at 13:37
add comment

4 Answers

Right, first off, let's deal with "Any code calling the ctor will need updating when new dependencies are added"; To be clear, if you're doing dependency injection and you have any code calling new() on an object with dependencies, you're doing it wrong.

Your DI container should be able to inject all the relevant dependencies, so you don't need to worry about changing the constructor signature, so that argument doesn't really hold.

As for the per-method vs. per-class injection idea, there are two major issues with per-method injection.

One issue is that your class's methods should share dependencies, it's one way to help make sure your classes are separated effectively, if you see a class with a large number of dependencies (probably more than 4-5) then that class is a prime candidate for refactoring into two classes.

The next issue is that in order to "inject" the dependencies, per-method, you'd have to pass them into the method call. This means that you'll have to resolve the dependencies before the method call, so you'll likely end up with a bunch of code like this:

var someDependency = ServiceLocator.Resolve<ISomeDependency>();
var something = classBeingInjected.DoStuff(someDependency);

Now, say you're going to call this method in 10 places around your application: you'll have 10 of these snippets. Next, say you need to add another dependency to DoStuff(): you're going to have to change that snippet 10 times (or wrap it in a method, in which case you're just replicating DI behaviour manually, which is a waste of time).

So, what you've basically done there is made your DI-utilising classes aware of their own DI container, which is a fundamentally bad idea, as it very quickly leads to a clunky design that's difficult to maintain.

Compare that to constructor injection; In constructor injection you're not tied to a particular DI container, and you're never directly responsible for fulfilling the dependencies of your classes, so maintenance is fairly headache-free.

It sounds to me like you're trying to apply IoC to a class containing a bunch of unrelated helper methods, whereas you might be better off splitting the helper class into a number of service classes based on usage, then using the helper to delegate the calls. This still isn't a great approach (helper classed with methods that do anything more complex than just deal with the arguments that are passed to them are generally just badly-written service classes), but it will at least keep your design a little cleaner.

(N.B. I've done the approach you're suggesting before, and it was a very bad idea that I have not repeated since. Turned out I was trying to separate out classes that really didn't need to be separated, and ended up with a set of interfaces where each method call required a near-fixed selection of other interfaces. It was a nightmare to maintain.)

share|improve this answer
1  
"if you're doing dependency injection and you have any code calling new() on an object with dependencies, you're doing it wrong." If you are unit testing a method on a class you have to instantiate it or do you use DI to instantiate your Code Under Test? –  StuperUser Apr 3 '12 at 13:29
    
@StuperUser Unit testing is a slightly different scenario, my comment only really applies to production code. As you're going to be making mock (or stub) dependencies for your tests via a mocking framework, each with a pre-configured behaviour and set of assumptions and assertions, you'll need to inject them by hand. –  Ed Woodcock Apr 3 '12 at 13:31
1  
That's the code that I'm talking about when I say "any code calling the ctor will need updating", my production code doesn't call the ctors. For these reasons. –  StuperUser Apr 3 '12 at 13:36
2  
@StuperUser Fair enough, but you're still going to be calling the methods with the required dependencies, which means the rest of my answer still stands! To be honest, I agree about the issue with constructor injection and forcing all dependencies, from a unit testing perspective. I tend to use property injection, as this allows you to only inject the dependencies you expect to need for a test, which I find is basically another set of implicit Assert.WasNotCalled calls without having to actually write any code ! :D –  Ed Woodcock Apr 3 '12 at 13:40
add comment

There are various kinds of inversion of control, and your question proposes only two (you can also use factory to inject dependency).

The answer is : it depends on the need. Sometimes it is better to use one kind, and another different kind.

I personally like constructor injectors, since the constructor is there to fully initialize the object. Having to call a setter later on makes the object not fully constructed.

share|improve this answer
add comment

You missed the one that at least for me is the most flexible - property injection. I use Castle/Windsor and all I need to do is add a new auto property to my class and I get the injected object without any problems and without breaking any interfaces.

share|improve this answer
    
I'm used to web apps and if these classes are in the Domain layer, called by the UI, which has its dependencies resolved already in a similar fashion to Property Injection. I'm wondering how to deal with classes that I can pass on the injected objects to. –  StuperUser Apr 3 '12 at 13:34
    
I also like property injection, simply so you can still use normal constructor parameters with a DI container, automatically differentiating between the resolved and non-resolved dependencies. However, as constructor- and property-injection are functionally identical for this scenario I chose not to mention it ;) –  Ed Woodcock Apr 3 '12 at 13:34
    
Property injection forces every object to be mutable and creates instances in an invalid state. Why would that be preferable? –  Chris Pitman Apr 3 '12 at 14:59
    
@Chris Actually, under normal conditions the constructor and property injection act pretty much identically, with the object being fully injected during resolution. The only time it could be considered to be "invalid" is during unit testing, when you're not going to be using the DI container to instantiate the implementation. See my a comment on my answer for my take on why this is actually beneficial. I appreciate that mutability could be an issue, but realistically you're only going to reference resolved classes through their interfaces, which will not expose the dependencies to edit. –  Ed Woodcock Apr 3 '12 at 16:50
add comment

It's depends, if the injected object is used by more than one method in the class, and inject in it on each method does not make sense, you need to resolve the dependencies for every method call, and but if the dependency is used only by one method inject in it on the constructor is not good, but since you are allocating resources that could never be used.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.