2

How to use Dependency Injection in multilevel class hierarchy? For example :-

public class ModuleClassViewModel
    {
        ModulePageClassServiceRepository _modulePageClassServiceRepository = null;
        public ModuleClassViewModel(ModulePageClassServiceRepository modulePageClassServiceRepository)
        {
            _modulePageClassServiceRepository = modulePageClassServiceRepository;
        }

        public IList<ModulePageClassObject> ModuleClassPageHierarchy(int? modulePageClassID, string SecureKey)
        {
            return _modulePageClassServiceRepository.ModuleClassPageHierarchy(....);
        }
}

and code for ModulePageClassServiceRepository is.......

public class ModulePageClassServiceRepository : IModulePageClassService 
    {
        ServiceDAO _serviceDAO = null
        public ModulePageClassServiceRepository(ServiceDAO  serviceDAO )
        {
            serviceDAO  = serviceDAO ;
         }

        public IList<ModulePageClassObject> ModuleClassPageHierarchy(ModuleClassPageHierarchyParameter moduleClassPageHierarchyParameter)
        {
            // call serviceDAO  and return result
        }
}

now as per DI if we want to use ModuleClassViewModel then we first need to inject ModulePageClassServiceRepository object and for ModulePageClassServiceRepository we need serviceDAO .... this hierarchy can grow to multiple level.... assume in Test class....

  public class TestDI
  {
    public void TestMethod()
        {
         ServiceDAO objServiceDAO = new ServiceDAO();

        ModulePageClassServiceRepository objModulePageClassServiceRepository  = new ModulePageClassServiceRepository (objServiceDAO );

        ModuleClassViewModel objModuleClassViewModel = new ModuleClassViewModel(objModulePageClassServiceRepository );

        //call method of objModuleClassViewModel 
        }

    }

Is this correct way to use dependency injection. here I need to first initialize complete hierarchy so my question is - Do I need to first initialize this complete hierarchy....or is there any other way to call ModuleClassViewModel class ???

SAL
  • 23
  • 5
  • You should use a DI container like Unity, Autofac, etc. When properly configured, it will remove the need for you manually inject dependencies. Also, creating interfaces for your classes will facilitate the DI process and make you code more flexible. – Big Daddy Feb 06 '14 at 14:59

3 Answers3

1

This code is working as per my tests.

I suggest you use the Enterprise library block Unity, in order to make it happen. To download it click here: http://msdn.microsoft.com/en-us/library/dn169621.aspx, or try to get it using NUget: https://www.nuget.org/packages/EnterpriseLibrary.Common/

  1. First of all, you need to change your design by making all classes to implement an interface. That would be:

    class ClassA : InterfaceA {...}
    class ClassB : InterfaceB {...}
    class ClassC : InterfaceC {...}
    
  2. Add references to these assemblies:

    • Microsoft.Practices.EnterpriseLibrary.Common.dll
    • Microsoft.Practices.ServiceLocation.dll
    • Microsoft.Practices.Unity.dll
    • Microsoft.Practices.Unity.Configuration.dll
    • Microsoft.Practices.Unity.Interception.dll
    • Microsoft.Practices.Unity.Interception.Configuration.dll
  3. In your real implementation put this in your start of the "ClassA" caller: (see more http://msdn.microsoft.com/en-us/library/ff648271.aspx)

    using Microsoft.Practices.Unity;
    
    (...)
    
    IUnityContainer myContainer = new UnityContainer();
    myContainer.RegisterType<InterfaceA,ClassA>();
    myContainer.RegisterType<InterfaceB, ClassB>();
    myContainer.RegisterType<InterfaceC, ClassC>();
    InterfaceA iA = myContainer.Resolve<InterfaceA>();
    
  4. In your test implementation, using the Moq framework (https://code.google.com/p/moq/) you will be able to do this:

    Mock<InterfaceB> interfaceB = new Mock<InterfaceB>();
    // Then you setup, which will make your ClassB "look like" something you want it to look like
    interfaceB.Setup(s => s.setupOfSomeMethod($withArgument1$)).Returns($shouldReturnThisValue$).Verifyable();
    InterfaceA classA = new ClassA(interfaceB.Object);
    // do your testing here.
    
0

The service locator pattern is to deal with this case: you can put all your service instance in a list, and use the locator to get them.

For you case, Class A depends on B, B depends on C. First, you should not let class depends on concrete classes, let classes depends on the interfaces. So A->IB, B->IC; then put the concrete classes into the service list. So the code will like this:

locator.add(IC, new C());
IC serviceC = locator.find(IC);
if (serviceC )
  { B = new B(serviceC);
    locator.add(IB, B);}

To create the class A, just follow the routine of creating B. So when you want to test class A using mock, you just just create two mock classes, one inherit from IB, one inherit from IC, and out them into the service list.

Matt
  • 6,010
  • 25
  • 36
  • let me describe this question again ..... i have three class A,B,C and this class depend on each other as A->B->C so if we want to use class A any where in code then first we need to inject dependency Class B in to Class A and Dependency Class C into Class B... this how it works in normal Dependency Injection..... and this chain dependency adds more complexity when we try to test Class A using Mocking...... I don't think Service Locator Pattern will work in this case... – SAL Feb 06 '14 at 14:24
  • Matt, Thanks for your quick response. I tried to understand [Service Locator pattern](http://stackoverflow.com/questions/1557781/whats-the-difference-between-the-dependency-injection-and-service-locator-patte). It solves one problem- (chain dependency). But how can I test this code in Unit Test case using Mock object as we cannot create Mock object for code having Service Locator – SAL Feb 06 '14 at 15:39
  • You can create mock service locator too. – Matt Feb 06 '14 at 15:42
0

IocServiceStack supports multi-level dependency injection.

https://github.com/rjinaga/IocServiceStack

http://www.iocservicestack.net/

Rajesh Jinaga
  • 169
  • 2
  • 3