-2

One of the "Service Locator" pattern drawbacks is that a caller can be misleaded about dependencies of a callee.

Ok, but what if I put dependencies as generic parameters at a class level:

class Node<T> where T : ISomeInterface, new()
{
  ISomeInterface obj
  public Node()
  {
     obj = new T();
  }
}

I have found a couple of opinions here. But I want a discussion to be continued.

The most significant counterargument is that dependency injecting using generics makes late binding unavailable. But who cares in most cases? What if my app does not need this feature?

I want to find some solid counterarguments.

p.s. new() constraint is not necessary, as you understand.

closed as primarily opinion-based by gnat, Eric King, user40980, GlenH7, Bart van Ingen Schenau Oct 3 '13 at 8:01

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 4
    "I want a discussion" -- "This site is all tour getting answers. It's not a discussion forum." – gnat Oct 1 '13 at 13:33
5

The linked article is a bit misleading, in my opinion. Yes, using Inversion of Control containers makes some errors appear at runtime rather than compile time. And in general, it makes the process of writing and maintaining your code more fragile. This applies to Service Locators or really any other IoC container in my experience. This does not make them anti-patterns.

The key thing is that if you don't need that sort of plugin behavior, then don't use it. All design decisions are a trade off, and in IoC's case, that late binding (and ease of testing) is what you get and runtime errors rather than compile time (and decreased readability/debug-ability) is what you pay.

Indeed, your default approach should just be making plain old objects that take parameters in their constructor. Once that's insufficient, then start worrying about fancy tricks.

  • Sage advice: don't use fancy stuff “just because”; only use it when you get something in return. – Donal Fellows Oct 1 '13 at 14:14
2

I would say that your solution is actually worse than the original.

  1. You're limiting yourself to types that have default constructor. What if you want to use a type that takes some configuration in its constructor?
  2. If you have a dependency that has a dependency that has a dependency, you end up with horrible types like Node<Foo<Bar<Baz>>>. This doesn't make much sense, especially since none of the members of the type actually depend on the type parameters.
  3. You need to specify the concrete type of dependency at compile time. This makes your code much less flexible and you can't for example switch the dependency just by editing a configuration file (which can be useful).
  4. How is new Node<Foo>() any better than new Node(new Foo())?

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