32

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
  • 66,094
  • 13
  • 157
  • 251
ChrisCa
  • 10,876
  • 22
  • 81
  • 118
  • 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
  • 225,310
  • 48
  • 427
  • 736
  • 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
  • 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
  • @MarkSeemann The problem with this approach is that you are now violating LSP with respect to IDependency interface since you now have two implementations (one stateful and one stateles) that can't be used interchangeably. In order to fix this the client should be changed to depend on a new interface ITransientDependency where the implementation is a stateless façade around the original dependency (like in your example). – Milos Mrdovic Jul 22 '22 at 19:44
  • @MilosMrdovic I agree that there seems to be an LSP violation somewhere, but since the question is so general, we can't tell exactly where. What are the invariants of `IDependency`? We don't really know, but I've interpreted the OP in such a way that the lifetime requirement is an implementation detail. If this is true, the LSP violater is the stateful implementation - not the [Decoraptor](https://blog.ploeh.dk/2014/08/24/decoraptor). – Mark Seemann Jul 23 '22 at 08:22
  • @MarkSeemann I see your point, the problem may indeed lie in the original implementation of IDependency. That's why I think you gave the best advice in your initial comment where you suggested rethinking the entire architecture. However, if the lifetime requirement is not an implementation detail (for whatever reason), then it appears a wrapper with a new interface and a different set of requirements, although a bit more complex, is a better option. – Milos Mrdovic Jul 23 '22 at 23:29
  • @MarkSeemann Just to elaborate a bit more: the above solution introduces an incompatible behavior of IDependency which creates problems of its own. The original implementation of IDependency obviously breaks MyService, but other services may need it. This would force OP to set up the DI container to inject a specific implementation of IDependency based on the type of the target service. That violates, not only LSP, but DIP as well because MyService, even though it looks like it depends on an interface, is actually tightly coupled to a particular implementation. Am I missing something? – Milos Mrdovic Jul 24 '22 at 00:33
  • 1
    @MilosMrdovic That seems fair, and I agree that my initial comment to the question is in general the better advice. FWIW, I can't remember the details of my thinking 11 years ago, but I think that the reason I also added an *answer* in addition to the comment was to provide a counter-argument to the other answers already being posted. The way that SO works, I couldn't effectively counter other answers with only a comment. – Mark Seemann Jul 24 '22 at 09:36
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,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    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
  • 142,167
  • 33
  • 283
  • 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
  • 1
    @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
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 3
    Please don't use a `Func` for that. That makes your code very hard to follow. – Steven Jan 10 '11 at 15:55
  • 12
    @Steven: So you've stated several times, with nothing to back up your claim. – Jon Skeet Jan 10 '11 at 16:03
  • @JonSkeet It's about communicating the intent and adhering to the principle of least astonishment. Func means nothing. IDependencyFactory.Create() means something very specific. Funcitonal programing is awesome. However, OO allows you to express yourself just a tad bit better. – Milos Mrdovic Jul 22 '22 at 20:35
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
  • 59,778
  • 26
  • 187
  • 249
Brian Ball
  • 12,268
  • 3
  • 40
  • 51