我已经阅读过有关IoC,DIP,DI和服务定位器的各种文章,但我有点困惑,因为有些文章的例子太模糊,而其他一些文章只有一些具体的例子而没有提及其他案例。
请您帮我解决一下这个问题,查看下面的示例并简要说明哪些示例符合哪种模式?
手动将接口传递给构造函数:
class Consumer
{
public Consumer(IStore store){...}
}
...
Consumer c = new Consumer(new ConcreteStore());
与第一个示例相同,但使用了第三方库(Unity,Windsor,Ninject)
与第一个示例相同,但使用BaseStore类而不是IStore接口
将依赖项传递给其他方法,而不是构造函数:
class Consumer
{
public BySomething(IStore store){...}
}
...
Consumer c = new Consumer();
c.BySomething(new ConcreteStore());
传递依赖关系掩盖在其他界面内部(此解决方案的奖励 - 当“世界”中发明了一些其他东西而消费者希望使用它们时,我们不必更改构造函数参数而只是更新IWorld;我们可以在测试时用其他东西完全取代整个世界:
interface IWorld
{
IDictionary<string,IStore> Stores { get; set; }
IDictionary<string,ICityMap> Maps { get; set; }
...
}
class Consumer
{
public Consumer(IWorld world){...}
public BySomething(string store, string city){...}
}
...
IWorld myWorld = new HeavenlyWorld();
... // adding stores, maps and whatnot
Consumer c = new Consumer(myWorld);
一个子问题:在这种情况下,IWorld是服务定位器还是不完全?
传递回调函数或委托(在本例中为.NET Action):
c.BySomething(store, city, new Action(() => {...} ));
我添加了这个案例,因为文章Inversion of Control声明每个回调都是IoC。这是真的吗?
答案 0 :(得分:2)
您列出的所有内容都是依赖注入的一种形式。
答案 1 :(得分:1)
每次将依赖项作为构造函数/方法参数传递时,都是Dependecy Injection。它可以是手动的,就像在大多数示例中一样,或者自动使用DI Container也称为IoC容器。
使用容器意味着使用deps的对象由容器构造。您可以直接向容器询问该服务,在这种情况下,有一个静态属性或方法(在asp.net mvc中认为DependecyResolver)公开该服务。在这种情况下,您正在使用服务定位器模式。 IWork 在您的示例中不是定位器,它只是一个依赖项。
要继续使用依赖项解析程序示例,请将所有相关类型注册到容器中,然后将容器构建为依赖项解析程序。然后asp.net mvc框架使用解析器(服务定位器 - SL)来实例化控制器,视图和所需的所有deps。
使用SL模式可以作为框架的一部分,但是如果你在应用程序中使用它来实例化对象,那就不行了,因为它将代码耦合到定位器。有时是唯一的解决方案,但99%你只是一个反模式。