1

this question is a follow-up of this question i posted last weekend.

As of now, i have something like this in my service layer which talks with UI in MVC application.

IDepartmentService deptService = kernel.Get<IDepartmentService>();
IList<Department> deptList = deptService.GetAllDepartments();

Everything is fine and DI is working as expected. However, for some reason if i decide to use Structuremap then my entire service layer needs to be changed. How do i abstract it out so that a change in DI tool wont affect my service layer or has minimum impact.

Community
  • 1
  • 1
NoobDeveloper
  • 1,877
  • 6
  • 30
  • 55

1 Answers1

2

However, for some reason if i decide to use Structuremap then my entire service layer needs to be changed.

That's not true. As shown in the previous thread the Service Layer doesn't know anything about the DI framework.

You should have a layer called composition root. This is the only layer which is aware of the DI framework and all the underlying layers. This is where you are doing the composition. So if you change the DI framework, the only place you need to make changes is in the composition root.

So you should absolutely get rid of kernel.Get<> calls from your service. Right now you are using Service Locator and not Dependency Injection. Service Locator is an anti-pattern. Your service layer should look like this:

public class MyService
{
    private readonly ISomeDependency dependency;
    public MyService(ISomeDependency dependency)
    {
        this.dependency = dependency;
    }

    public void SomeMethod()
    {
        // do something with the dependency here
    }
}

instead of:

public class MyService
{
    private readonly ISomeDependency dependency;
    public MyService()
    {
        this.dependency = kernel.Get<ISomeDependency>();
    }

    public void SomeMethod()
    {
        // do something with the dependency here
    }
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Your 1st code block is exactly what i have in my service layer. However, What if i need an instance of ISomeAnotherDependency in only one method of the many methods of MyService class to fetch data? Should i put it in constructor ? That is why i have kernel.Get<> method as of now , so that i can get instance of ISomeAnotherDependency. I want to get rid of it and hence was thinking of some ILocator.Get which will give me instance of a desired type. Do you think this is a bad approach ? – NoobDeveloper Aug 01 '13 at 10:37
  • 1
    Yes, pass it as constructor dependency. Constructor injection is used to pass dependencies to the class without which this class cannot work properly. In your case even if you have only 1 method that requires this dependency, it is still a required dependency for the service to work properly. Also never use the Service Locator pattern. This is an ANTI PATTERN. You should work with the DI framework only in the composition root. – Darin Dimitrov Aug 01 '13 at 11:28
  • Perfect. Thanks again. I have marked your reply as answer. Just one more question. How do i test my service layer ? should i manually new up the dependency as pass it on constructor and test the service layer methods ? – NoobDeveloper Aug 01 '13 at 18:34
  • If you want to test your service layer in isolation, ideally, you should use a mocking framework to pass a mocked instance of the dependency in your service for the unit test. This way you have complete control over the behavior of this dependency and you have the possibility to unit test in isolation all the functionality present in this service layer. – Darin Dimitrov Aug 01 '13 at 20:34
  • In the example you gave,MyService depends on ISomeDependency. So should i use mocking framework (Moq) to mock ISomeDependency ? or should i mock the DI tool ? I am little bit confused over this. As of now i am not using any mocking framework and instead manually newing up the MyService and ISomeDependency to test methods from MyService. Thanks for your time. – NoobDeveloper Aug 02 '13 at 06:01
  • 1
    In your unit tests you do not use any DI. You could use a mocking framework if you want to inject a mocked `ISomeDependency` into the service or if you don't want to use a mocking framework you could always write a mocked implementation of this interface yourself for the unit test which is usually lot of work and the reason why people created mocking frameworks such as Moq. – Darin Dimitrov Aug 02 '13 at 06:19