c# - 解析接口(interface)时,Ninject 未解析为已配置的单例

标签 c# dependency-injection ninject

我有一个使用 Ninject 作为其 DI 的应用程序。我正在添加一些新类,但它们并没有按照我认为应该的方式得到解决。

我有一个类Foo,它实现了ISomething接口(interface)。如果我像这样配置绑定(bind):

kernel.Bind<Foo>().ToSelf().InSingletonScope();
kernel.Bind<ISomething>().To<Foo>();

然后执行:

var foo1 = kernel.Get<Foo>();
var foo2 = kernel.Get<ISomething>();

这两个变量具有 Foo 类的不同实例。

如果我将绑定(bind)更改为:

kernel.Bind<Foo>().ToSelf().InSingletonScope();
kernel.Bind<ISomething>().ToMethod(ctx => ctx.Kernel.Get<Foo>());

然后执行:

var foo1 = kernel.Get<Foo>();
var foo2 = kernel.Get<ISomething>();

这两个变量具有相同实例。

我的理解是,在第一种情况下,它应该将 ISomething 解析为 Foo,而后者又会解析为自身的单例。是我的理解有误,还是有其他问题?必须手动解决它似乎有点多余。

最佳答案

当您在注册中省略生活方式时,按照惯例,Ninject 将使用 transient 生活方式。这意味着:

kernel.Bind<ISomething>().To<Foo>();

相当于:

kernel.Bind<ISomething>().To<Foo>().InTransientScope();

加上生活方式,就更容易发现问题了:

kernel.Bind<Foo>().ToSelf().InSingletonScope();
kernel.Bind<ISomething>().To<Foo>().InTransientScope();

或者更清楚:

kernel.Bind<Foo>()       .To<Foo>().InSingletonScope();
kernel.Bind<ISomething>().To<Foo>().InTransientScope();

在这里您可以看到您正在将 Foo 注册为单例和 transient 。这种错误配置是一个常见的陷阱,称为 Ambiguous Lifestyles :

When multiple registrations with a different lifestyle map to the same component, the component is said to have ambiguous lifestyles. Having one single component with multiple lifestyles will cause instances of that component to be cached in different ways and this can lead to behavior that you might not expect.

某些 DI 容器确实包含可用于检测此类错误配置的验证机制,但我熟悉的所有 DI 容器都允许您以这种方式意外地错误配置容器。

关于c# - 解析接口(interface)时,Ninject 未解析为已配置的单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60953235/

相关文章:

c# - HttpWebRequest 将凭据传递给下一个 HttpWebRequest

c# - 从控制台应用程序从网站读取 XML 文件

javascript - 在mvc中使用jquery更新@RenderBody

android - 为AndroidViewModel创建ViewModelFactory的正确方法是什么

asp.net-mvc-5 - nuget中用于与WEB API集成的所有这些Ninject包是什么?

c# - DataGridView 没有列

dependency-injection - 有人可以解释异常:未初始化Module.DEFAULT_REFLECTOR的依赖关系

java - Spring - 使用@Configurable 和@Value 注释用新运算符创建对象

unit-testing - 在测试方法中本地覆盖 Ninject 绑定(bind)以绑定(bind)模拟对象

Ninject transient 范围