没有服务定位器的IOC

时间:2015-07-09 09:01:36

标签: c# oop design-patterns inversion-of-control service-locator

假设我有3个类,ProgramA(带有依赖项D1D2)和B(带有依赖项D3D4)。 Program初始化一个IOC容器并在创建A的实例之前注册一堆类型。

class Program
{
    static void Main(string[] args)
    {
        IOC ioc = new IOC();
        //register types

        A a = ioc.Resolve<A>();
    }
}

稍后,a需要创建B的实例,将其两个依赖项注入构造函数。

问题a应如何解决B的依赖关系?我被引导相信传递IOC容器,即将其注入A是服务定位器模式,这是不好的。如果B创建了C及其依赖项,B也需要注入容器,并且整个代码中的容器都会被填满。这听起来像是一场测试噩梦。使用全局静态听起来不太好。

3 个答案:

答案 0 :(得分:2)

它实际上很简单。如果B需要B,则应接受public class A { private readonly D1 d1; private readonly D2 d2; private readonly B b; public A(D1 d1, D2 d2, B b) { this.d1 = d1; this.d2 = d2; this.b = b; } } public class B { private readonly D3 d3; private readonly D4 d4; private readonly C c; public B(D3 d3, D4 d4, C c) { this.d3 = d3; this.d4 = d4; this.c = c; } } 作为构造函数参数:

A

通过这种方式,您可以递归地构建对象图,并且可以获得非常深的对象图,这完全没问题。这样,您只需要应用程序启动路径中的容器(例如,组合根)。

B是否需要B&#39;以后,或者只是有时,或者几乎没有任何关系。构建对象图应该很快,因此<script> $(document).ready(function () { $("#submit1222").on('click', function () { var name = $("#name1222").val(); var dataString = 'filter=' + name; if (name == '') { document.getElementById('error1').innerHTML = "Please Fill All Fields"; } else { $.ajax({ type: "POST", url: '<?php echo $action; ?>', data: dataString, cache: false, success: function (result) { document.getElementById('container').innerHTML = result; } }); } return false; }); }); </script> 是否不必要地创建应该不是问题。

答案 1 :(得分:1)

理想情况下,您不应该只为了解决依赖关系而向您的类注入容器。相反,您可以在单独的位置注册实例,可能是您的启动类,其中运行时应用程序应该能够从带有容器的已注册实例自动解析依赖关系。

查看以下示例IOC容器通常如何注册其实例

注册

  

SimpleIoc.Default.Register&LT; IDataService,DataService&gt;();   SimpleIoc.Default.Register&LT; MainViewModel&gt;();
  SimpleIoc.Default.Register&LT; SecondViewModel&gt;();

解决

  

SimpleIoc.Default.GetInstance&LT; MainViewModel&gt;();

答案 2 :(得分:0)

  

稍后,A需要创建一个'B'的实例,   将它的两个依赖项注入构造函数。

在这种情况下,A必须依赖BFactory才能为其创建B