【问题标题】:Ninject not resolving to a configured singleton when resolving an interface解析接口时,Ninject 未解析为已配置的单例
【发布时间】:2020-07-12 03:51:46
【问题描述】:

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

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

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

然后做:

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

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

如果我将绑定更改为:

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,而后者又会解析为自身的单例。是我的理解不正确,还是有其他问题?手动解决似乎有点多余。

【问题讨论】:

  • 是否可以这样做kernel.Bind&lt;ISomething&gt;().To&lt;Foo&gt;().InSingletonScope(); 并且您仍然得到两个实例?
  • 我仍然得到两个不同的实例。
  • 太糟糕了。我希望 Ninject 能做一些内部魔法并解决相同的范围......但显然这不起作用。
  • @adrianbanks 您对 Ninject 的理解不正确。这些是两个单独的注册,因此是两个单独的实例。同样的方法也发生在 .net 核心上,你还必须使用委托工厂 service.AddSingleton&lt;ISomething&gt;(_ =&gt; _.GetService&lt;Foo&gt;());

标签: c# dependency-injection ninject


【解决方案1】:

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

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 注册为单例和瞬态。这种错误配置是一个常见的陷阱,称为Ambiguous Lifestyles

当具有不同生活方式的多个注册映射到同一个组件时,该组件被称为具有模棱两可的生活方式。拥有具有多种生活方式的单个组件会导致该组件的实例以不同的方式缓存,这可能会导致您可能无法预料的行为。

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

【讨论】:

    猜你喜欢
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 2018-04-13
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多