什么是 IoC 容器中的自绑定?
What is self-binding in an IoC container?
我见过像 Ninject 这样的框架以及 Stack 上的帖子都谈到了在使用如下代码中的依赖项注入框架时的自我绑定。
Bind<Samurai>().To<Samurai>();
他们甚至为此使用了特殊语法:
Bind<Samurai>().ToSelf();
为什么要将类型绑定到自身?我没有看到任何实际应用程序可能有用并有助于减少代码中的依赖性。这难道不意味着对类型的引用会简单地解析为自身吗?
在应用依赖注入并遵守 Dependency Inversion Principle, the common advice is to program to interfaces, not implementations 时。这就是为什么大多数时候您会看到从抽象到实现的绑定:
Bind<IWarrior>().To<Samurai>();
这意味着组件 依赖 在编译时 IWarrior
,而你 注入 一个 Samurai
在运行时间。
然而,在某些情况下,从具体组件到自身的映射是有意义的。换句话说,如果 'someone' 需要 Samurai
,您可以提供 Samurai
.
最突出的情况是在解析根类型时。根类型是依赖图的顶部;根类型直接从容器中解析。所有其他组件都是根类型的直接或间接依赖项。
您经常会看到这些根类型由它们的具体类型解析,例如,在处理 UI 框架时会发生这种情况。此类示例有 Web Forms Page
s、MVC Controller
s、Web API ApiController
s 等
一些 DI 容器无论如何都允许解析具体的未注册类型(尽管近年来 .NET 的几个 DI 容器默认禁用了解析具体未注册类型的能力)。这可能会让您认为自绑定是多余的,但情况并非总是如此。显式添加此类绑定可让容器了解此类绑定的存在。这具有使用容器的诊断能力(如果存在)来扫描对象图以查找错误的优点。如果没有这样的功能,通常可以迭代已知的注册并在单元测试中进行一些验证。为了在迭代容器的注册时使此类验证有意义,所有根类型都需要在容器中注册。否则此验证过程将导致假阴性。
你想要告诉 DI 容器自绑定的另一个原因是当你需要使用不同于容器默认生活方式的生活方式注册类型时。大多数容器会给你一个 Transient 实例,以防类型未注册。
我见过像 Ninject 这样的框架以及 Stack 上的帖子都谈到了在使用如下代码中的依赖项注入框架时的自我绑定。
Bind<Samurai>().To<Samurai>();
他们甚至为此使用了特殊语法:
Bind<Samurai>().ToSelf();
为什么要将类型绑定到自身?我没有看到任何实际应用程序可能有用并有助于减少代码中的依赖性。这难道不意味着对类型的引用会简单地解析为自身吗?
在应用依赖注入并遵守 Dependency Inversion Principle, the common advice is to program to interfaces, not implementations 时。这就是为什么大多数时候您会看到从抽象到实现的绑定:
Bind<IWarrior>().To<Samurai>();
这意味着组件 依赖 在编译时 IWarrior
,而你 注入 一个 Samurai
在运行时间。
然而,在某些情况下,从具体组件到自身的映射是有意义的。换句话说,如果 'someone' 需要 Samurai
,您可以提供 Samurai
.
最突出的情况是在解析根类型时。根类型是依赖图的顶部;根类型直接从容器中解析。所有其他组件都是根类型的直接或间接依赖项。
您经常会看到这些根类型由它们的具体类型解析,例如,在处理 UI 框架时会发生这种情况。此类示例有 Web Forms Page
s、MVC Controller
s、Web API ApiController
s 等
一些 DI 容器无论如何都允许解析具体的未注册类型(尽管近年来 .NET 的几个 DI 容器默认禁用了解析具体未注册类型的能力)。这可能会让您认为自绑定是多余的,但情况并非总是如此。显式添加此类绑定可让容器了解此类绑定的存在。这具有使用容器的诊断能力(如果存在)来扫描对象图以查找错误的优点。如果没有这样的功能,通常可以迭代已知的注册并在单元测试中进行一些验证。为了在迭代容器的注册时使此类验证有意义,所有根类型都需要在容器中注册。否则此验证过程将导致假阴性。
你想要告诉 DI 容器自绑定的另一个原因是当你需要使用不同于容器默认生活方式的生活方式注册类型时。大多数容器会给你一个 Transient 实例,以防类型未注册。