什么是IoC容器中的自我绑定?

时间:2017-01-04 02:15:45

标签: c# dependency-injection ninject ioc-container

我已经看到像Ninject这样的框架以及Stack上的帖子在使用依赖注入框架时会谈到自我绑定,如下面的代码所示。

Bind<Samurai>().To<Samurai>();

他们甚至会采用特殊语法:

Bind<Samurai>().ToSelf();

为什么要将类型绑定到自身?我没有看到任何有用的实际应用程序,有助于减少代码中的依赖关系。这不就意味着对类型的引用会简单地解决它自己吗?

1 个答案:

答案 0 :(得分:5)

在应用依赖注入并遵守Dependency Inversion Principle时,常见建议为to program to interfaces, not implementations。这就是为什么大多数时候你会看到从抽象到实现的绑定:

Bind<IWarrior>().To<Samurai>();

这意味着组件在编译时会依赖IWarrior,我们会在运行时注入Samurai

然而,在某些条件下,从具体组件到自身的映射是有意义的。换句话说,如果“某人”请求Samurai,我们会向其提供Samurai

最突出的情况是解析根类型。根类型是依赖关系图的顶部;根类型直接从容器中解析。所有其他类型都是根类型的直接或间接依赖。

通常,您会看到这些根类型是通过其具体类型解决的,并且通常我们正在处理UI框架。例如,Web表单Page,MVC Controller,Web API ApiController等。

大多数DI容器都允许解决具体的未注册类型。这可能会让您相信自我绑定是多余的,但情况并非总是如此。明确地添加这样的绑定可以让容器知道这种绑定的存在。这具有使用容器的诊断能力(如果存在)来扫描对象图以查找错误的优点。如果没有这样的功能,通常可以迭代已知的注册并在单元测试中进行一些验证。为了使这种验证在迭代容器的注册时有意义,所有根类型都需要在容器中注册。否则,此验证过程将导致误报。

您想要告诉DI容器自我绑定的另一个原因是容器不允许解析未注册的类型,或者您需要使用与容器的默认生活方式不同的生活方式注册类型。如果未注册类型,大多数容器都会为您提供 Transient 实例。