1

here's an example of what i am talking about

public interface IService<T>
    where T : class
{
    List<T> GetAll();
    T GetById(object id);
    .......... other methods here
}

public class Service<T> : IService<T>
    where T : class
{
    ... implement interface here
}

public class ServiceClient
{
    private readonly IService<User> _service;

    public ServiceClient(IService<User> service)
    {
        _service = service;
    }

    public ServiceClient() : this(new Service<User>()){}
}

can someone tell me the difference between this and a Dependency Resolver? I normally Use SimpleInjector for Dependency Injection, I just want to know the benefits of the Container over doing the above..

Thanks

Update

okay lets say I have setup my Containers now and removed the 'this' constructor initialization, I Want to now Test ServiceClient

Let use MS unit test for snippet

[TestMethod]
public void Given_Something_Should_Success()
{
    // Arrange

    // how do i make an instance of this in a test without adding the 'new Service<User>()' part
    ServiceClient client = new ServiceClient(new Service<User>());
}

and without changing my ServiceClient constructor to do this. Is it even possible to do that at this level? Sorry if this is a noob question i'm just trying to understand some things about it.

public ServiceClient(IService<User> service = null)
{
    _service = service ?? new Service<User>();
}
  • The pattern that you use where you have a default constructor that calls into an overloaded constructor (as in `public ServiceClient() : this(new Service())` is an anti-pattern called [Bastard Injection](https://stackoverflow.com/questions/7099406/). This anti-pattern is a specialized form of the [Control Freak anti-pattern](https://stackoverflow.com/questions/11330877/) and a violation of the [Dependency Inversion Principle](https://en.wikipedia.org/wiki/Dependency_inversion_principle). – Steven Feb 03 '17 at 10:48

4 Answers4

4

See this line of code:

public ServiceClient() : this(new Service<User>()){}

Now the ServiceClient is aware of Service<User> class and the assembly where the ServiceClient is will not build without having a reference to the assembly where Service<User> class is located. Furthermore, if Service<User> has additional methods which are not in IServiceUser<User>, then the developer may do this within the class:

(this._service as Service<User>).SomeMethodNotBelongingToTheInterface();

Now one can argue that an irresponsible developer will do that sort of thing, but that is beyond the point here.

To be totally decoupled from the concrete implementations, you should never call new and leave this to the Composition Root. Both your classes and your assembly should only work with the interfaces and be totally unaware of the concrete implementations. This guarantees that you can plug any implementation at the composition root level, and everything will work.

This does not mean that even POCO classes without behavior should be behind interfaces but just classes that require plug and play sort of behavior.

If you follow this pattern, you can also create architectural diagrams within Visual Studio and instruct which layer can have references to which assemblies. During build, the build will fail (if configured to fail) if the developer creates a reference to an assembly they are not allowed to reference.

At the composition root level, it is up to you whether you want to plug the classes into each other using an IoC container or doing it manually. But why do it manually if there are good tools (IoC containers) which can do this for you. You can have one config file where all the test classes are and another where the real classes are. You can instruct your whole program to run with either configuration with just one line of code: This is what I mean by plug and play. The whole idea behind dependency injection, loose coupling etc. is that your classes should not have code which is written against a concrete implementation.

CodingYoshi
  • 25,467
  • 4
  • 62
  • 64
0

In Container you would register your class and interface. Benefits are , you have one ioc class which will take care of providing you right type. So you can program against interface. and you do not need to new up in your code. this gives you also flexibility when you have to manage scope or mock some class. Here is some example how you register via IoC (Autofac)

builder.RegisterInstance(new ServiceClient())
   .As<IService>();
0

What using a Container gives you is a centralised place in your application to specify how your dependencies should be resolved.

Imagine you have many classes that wants to inject the same implementation of IService. By using your approach above, you would have to write that same code for all of those classes. If you would have used a container, specifying it there would be enough.

Also, many DIs gives you more functionality for sharing instances, maintaining life cycles of your injections etc, provide dependencies to your dependencies etc.

Fredrik Lundin
  • 8,006
  • 1
  • 29
  • 35
  • It's not so much that a Container gives you a centralized place. It's actually Dependency Injection does so. Both a Container and the practice of [Pure DI](http://blog.ploeh.dk/2014/06/10/pure-di/) have the same effect of the appearance of a [Composition Root](http://blog.ploeh.dk/2011/07/28/CompositionRoot/). – Steven Feb 03 '17 at 10:41
0

This is called Bastard injection and you shouldn't do this because is totally against the purpose of dependency inversion: to create decoupled and maintainable code. If you use a default implementation it means that you have to reference the project that contains the implementation of your service. Or worst you probably create the implementation of your service in the same library where it lives the interface.

On the other hand you might have a good default implementation. For example you might define this interface:

public interface IClock
{
    DateTime Now { get; }
}

The obvious implementation of this interface is

public class Clock : IClock
{
    public DateTime Now => DateTime.Now;
}

I wouldn't use though a public constructor for this, I would inject it via a Property and leave the constructor for another implementation (maybe a mock from your tests). Also SimpleInjector I think would shout about having two constructors. It is a tool which made me to read more about these ideas.

When the IService's implementation is something that talks with a database, or HTTP service, or a remote one, or with 3rd party library or with file system, then these are good reasons for you create a separate project, reference the one you defined the interface, create the implementation, then in your place where you setup the simple injector, you can bind the interface with the implementation (which requires here to reference both projects). If on a later time you need a diferent implementation you can simply repeat the process and change the composition root.

Adrian Iftode
  • 15,465
  • 4
  • 48
  • 73