31

I have some code that looks something like this:

public MyService(IDependency dependency)
{
    _dependency = dependency;
}

public Message Method1()
{
    _dependency.DoSomething();

}

public Message Method2()
{
    _dependency.DoSomething();  
}

public Message Method2()
{
    _dependency.DoSomething();  
}

Now I have just realised that because the dependency object contains internal state information. I need to new up a new instance of it in each method call

So what is the best way to do this and still not have a concrete instance newed up ?

Would you use an IoC container and make a call to to the container in each and every one of the methods? Or is there a slicker way where you can only make one call to the container?

What if I wasn't using an IoC container - would there be a way to not new up a concrete instance in each method?

Wim Coenen
  • 64,994
  • 13
  • 151
  • 241
ChrisCa
  • 10,518
  • 21
  • 79
  • 117
  • 5
    Your best options is really to rethink the entire architecture. Most of the answers below address the symptom by creating a leaky abstraction. The end result is that you win nothing from using DI, and you might as well just new up the dependency directly. – Mark Seemann Jan 10 '11 at 18:10

5 Answers5

38

Most of the answers here so far suggest that you change the injected dependency type to some sort of Abstract Factory (a Func<T> is also an Abstract Factory) to address the issue. However, if you do that it would be a leaky abstraction because you would let the knowledge of a particular implementation determine the design of the consumer. This violates the Liskov Substitution Principle.

A better option is to keep MyService as it is, and then create a wrapper for IDependency that addresses the particular lifetime issue:

public class TransientDependencyWrapper : IDependency
{
    public void DoSomething()
    {
        new MyStatefulDependency().DoSomething();
    }
}

Inject that into MyService instead of directly injecting the original implementation (MyStatefulDependency).

If you want to abstract away the creation of the dependency, you can always inject an Abstract Factory at this level.

Mark Seemann
  • 218,019
  • 46
  • 414
  • 706
  • 1
    Would you do the same thing if the Dependency didn't automatically dispose? Or would you just move to an IoC container at that point? – RobertTheGrey Jan 10 '11 at 18:48
  • This is the best answer, better than mine. – Rex M Jan 10 '11 at 19:03
  • 1
    @RobertTheGrey: As long as you hard-code it like I did in the example, you could explicitly dispose the instance again directly in the implementation. But you could also implement it by injecting an Abstract Factory into the wrapper and then let a container manage the lifetime of the created instances. Castle Windsor's Type Factory Facility comes to mind here. – Mark Seemann Jan 10 '11 at 19:21
  • @MarkSeemann How is that gonna work if I have other dependencies for MyStatefulDependency? – Ufuk Hacıoğulları Apr 01 '12 at 13:12
  • Just inject an Abstract Factory into the Virtual Proxy: http://blog.ploeh.dk/2010/01/20/EnablingDIForLazyComponents.aspx – Mark Seemann Apr 04 '12 at 05:50
  • 1
    @zloidooraque To be honest, I can't remember what I had in mind when I wrote about the LSP violation, but injecting an Abstract Factory *would* violate SOLID because it'd violate the DIP (*the client defines the interface*) and the ISP (*clients should not be forced to depend on more than they need*). – Mark Seemann Sep 13 '15 at 12:32
10

It sounds like you ought to inject a provider/factory. How you represent that is up to you (and what your IoC supports) - it could be as simple as:

public MyService(Func<IDependency> dependencyProvider)
{
    this.dependencyProvider = dependencyProvider;
}

public Message Method1()
{
    IDependency dependency = dependencyProvider();
    dependency.DoSomething();    
}

... or you could have an interface for this specific factory type, or a generic IFactory<T> etc. There are all kinds of possibilities - but the core bit is that you inject what you need, which in this case is "a way of creating a new implementation of IDependency on each call".

Jon Skeet
  • 1,335,956
  • 823
  • 8,931
  • 9,049
  • 1
    Please don't use a `Func` for that. That makes your code very hard to follow. – Steven Jan 10 '11 at 15:56
  • 4
    @Steven: I don't see why. It's a delegate which you can call whenever you need to get a value. How would `IProvider` or whatever make the code easier to follow? – Jon Skeet Jan 10 '11 at 16:02
  • @JonSkeet Assuming I have other dependencies for IDependency, how can I make the container 'implement' this delegate and resolve it,provide a new instance each time? – Ufuk Hacıoğulları Apr 01 '12 at 13:14
  • @UfukHacıoğulları: That would entirely depend on your IoC container, to be honest. – Jon Skeet Apr 01 '12 at 13:31
  • @JonSkeet I found an [example](http://stackoverflow.com/questions/2600277/funct-injecting-with-windsor-container), thanks. – Ufuk Hacıoğulları Apr 01 '12 at 14:19
5

If you need to create multiple instances of an injected type, you should inject an IDependencyFactory instead which would be responsible for controlling instance lifecycles:

interface IDependencyFactory
{
    IDependency GetInstance();
}
Rex M
  • 138,842
  • 31
  • 279
  • 313
  • +1. I absolutely favor this answer over Darin's and Jon's answers, because using a `Func` just makes your code to vague and cryptic. It just doesn't follow the principle of least surprise. – Steven Jan 10 '11 at 15:54
  • 2
    @Steven I can't usually knock @Jon Skeet but in this type of scenario, I've always been glad I used interfaces and rarely that I used delegates. So much easier to hide crazy, unexpected requirements behind the interface. – Rex M Jan 10 '11 at 16:01
  • 3
    @Rex M: On the other hand, if all you need is "create an instance" that's exactly why a `Func` can be *more* readable than a new interface. If I see a `Func`, I know exactly what I can do with it: call it to create a new instance. I know there won't be "new, crazy requirements" around it. If you really need something more complicated, sure, an interface gives you more power - but if you only need the one piece of behaviour, why not use a delegate? – Jon Skeet Jan 10 '11 at 16:05
  • 1
    @Jon everyone brings their own experience to the table :) in mine, I usually end up needing more power down the road, and I can't count how many times I've gone "wow, I am so glad I used an interface here." If a simple case works though, definitely use it. A really good example I could run into here would be wanting to change the backing implementation in the middle of the runtime, without disrupting the injected instances. That kind of thing comes up a lot on my projects. – Rex M Jan 10 '11 at 16:11
  • @Jon: I don't think it’s that obvious that a `Func` will always create a new T. Perhaps it's a convention you and your team follows, but I’ve seen people raise eyebrows on such construct. I rather make it very explicit what it is. Declaring it as an interface helps a lot. The problem gets even worse when you inject something like `Func`, because what should such a delegate return? The current time? Is that obvious? What if some class wants to get the current local time while another class needs the first day of the current month? How do you configure your DI framework for this? – Steven Jan 10 '11 at 16:16
  • 2
    @Steven: It needn't always create a new T, but then neither does an interface, unless you document it as an absolute requirement. I do take your point that my previous wording was too fast and loose, but I still think that `Func` is a perfectly good type to use in many of these situations. Not all, but many. – Jon Skeet Jan 10 '11 at 16:21
  • @Jon: What I do miss sometimes in C# however, is -like in Java- do define an implementation of an interface inline, just like we do with lambda's. That would be a hybrid of your Func and our interface solution. – Steven Jan 10 '11 at 16:22
  • 1
    @Steven: I miss that *very occasionally* but given the choice between only having lambda expressions and only having anonymous inner classes, I know which one I'd pick ;) – Jon Skeet Jan 10 '11 at 16:22
  • @Jon: I'd pick the former too :-) But are they mutally exclusive? Have you got a blogpost on that? – Steven Jan 10 '11 at 16:25
  • @Steven: Nope, I don't have a blog post on it. The object initializer syntax would make it tricky - even for interfaces, due to "calling" interface constructors for COM. – Jon Skeet Jan 10 '11 at 17:16
  • @Jon: It could be tricky, but perhaps it is possible for the C# compiler to implicitly convert a lambda to a interface definition. Something like this: `IDependencyFactory f = () => new Dependency();`. Because this construct is currently illegal (as far as I can see) it might be possible. Of course it could give conflicts when in method overload situations. That would make such a feature break existing code, which is never nice. – Steven Jan 10 '11 at 18:28
3

You could do it like this:

private readonly Func<IDependancy> _dependancy;
public MyService(Func<IDependancy> dependancy)
{
    _dependancy = dependancy;
}

public Message Method1()
{
    _dependancy().DoSomething();
}

public Message Method2()
{
    _dependancy().DoSomething();  
}

public Message Method3()
{
    _dependancy().DoSomething();  
}

And then:

var service = new MyService(() => new SomeConcreteDependency());
service.Method1();
service.Method2();
service.Method3();
Darin Dimitrov
  • 994,864
  • 265
  • 3,241
  • 2,902
1

First two ideas that come to my head are

  1. Don't take it in on the constructor, but take it in on each method.
  2. Instead of passing an instance into the constructor, pass in a factory or a Func<IDependency> that will create a new instance each time you call the func.
Ruben Bartelink
  • 57,716
  • 25
  • 179
  • 233
Brian Ball
  • 11,642
  • 3
  • 37
  • 50