2014-02-06 34 views
1

如何在多级别层次结构中使用依赖注入? 例如: - 对于ModulePageClassServiceRepository如何在多级类层次结构中使用依赖注入?

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

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

和代码.......

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

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

按DI如果我们要使用ModuleClassViewModel那么我们首先需要注入ModulePageClassServiceRepository对象,对于ModulePageClassServiceRepository我们需要serviceDAO ....这个层次可以长到多级.... 承担测试类....

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

     ModulePageClassServiceRepository objModulePageClassServiceRepository = new ModulePageClassServiceRepository (objServiceDAO); 

     ModuleClassViewModel objModuleClassViewModel = new ModuleClassViewModel(objModulePageClassServiceRepository); 

     //call method of objModuleClassViewModel 
     } 

    } 

这是使用依赖注入的正确方法。在这里我需要首先初始化完整的层次结构,所以我的问题是 - 我是否需要首先初始化这个完整的层次结构....或者是否有任何其他方式来调用ModuleClassViewModel类?

+0

你应该使用这样团结,Autofac等一个DI容器如果配置正确,它会删除需要您手动注入依赖。另外,为你的类创建接口将促进DI过程,并使你的代码更加灵活。 –

回答

1

此代码按照我的测试工作。

我建议你使用企业库块Unity,以使其发生。 要下载请点击这里:http://msdn.microsoft.com/en-us/library/dn169621.aspx,或者尝试使用的NuGet获得它:https://www.nuget.org/packages/EnterpriseLibrary.Common/

  1. 首先,你需要使所有的类来实现的接口改变设计。这将是:

    class ClassA : InterfaceA {...} 
    class ClassB : InterfaceB {...} 
    class ClassC : InterfaceC {...} 
    
  2. 添加对这些组件:

    • Microsoft.Practices.EnterpriseLibrary.Common.dll
    • Microsoft.Practices.ServiceLocation.dll
    • Microsoft.Practices。 Unity.dll
    • Microsoft.Practices.Unity.Configuration.dll
    • Microsoft.Practices.Uni ty.Interception.dll
    • Microsoft.Practices.Unity.Interception.Configuration。DLL
  3. 在你真正实现把这个在您的 “ClassA的” 来电者的开始: (详见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. 在您的测试实现,使用起订量框架(https://code.google.com/p/moq/)你将能够做到这一点:

    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

感谢您使用此解决方案。这是我正在寻找的确切的事情。 – SAL

0

The service locator pattern就是要处理这种情况:你可以把你所有的服务实例放在一个列表中,并使用定位器来获取它们。

对于你的情况,A类依赖于B,B依赖于C.首先,你不应该让类取决于具体类,让类取决于接口。所以A-> IB,B-> IC;然后将具体的类放入服务列表中。因此,代码会是这样的:

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

要创建A级,只要按照创建B.所以,当你想用模拟测试A级,你才刚刚创建两个模拟类的常规,从一个继承IB,一个从IC继承而来,并将它们放到服务列表中。

+0

让我再次描述这个问题.....我有三个类A,B,C,这个类相互依赖为A→B-> C,所以如果我们想要使用类A,我们需要注入依赖类B到类A和依赖类C到类B ...这是它如何在正常的依赖注入中工作.....并且这个链依赖增加了更多的复杂性,当我们尝试使用嘲笑测试类A时......我不认为Service Locator Pattern会在这种情况下工作...... – SAL

+0

@SAL,请参阅我在答案中的更新。 – Matt

+0

Matt, 感谢您的快速响应。 我试图理解[服务定位器模式](http://stackoverflow.com/questions/1557781/whats-the-difference-between-the-dependency-injection-and-service-locator-patte)。 它解决了一个问题 - (链依赖)。但是,如何使用Mock对象在单元测试案例中测试此代码,因为我们无法为具有服务定位器的代码创建模拟对象 – SAL