Ninject 与 WhenInjectedInto 扩展方法绑定
我觉得我错过了一些明显的东西。我已经阅读了这里的几个相关问题,并且阅读了 Ninject 维基上更新的上下文绑定页面,但可惜它仍然不起作用。
我正在尝试改造使用工厂模式的遗留应用程序以使用 Ninject。
我有 1 个接口(IInterface),由 2 个类(ClassB 和 ClassC)实现。 IInterface 有一个 load 方法。在ClassB的load方法中,它实例化ClassC,然后执行它的load方法。
基本上程序流程是ClassA创建ClassB并执行load方法。在加载方法中,ClassB 创建了执行一些工作的 ClassC。
我的绑定设置如下...
Bind<IInterface>().To<ClassC>().WhenInjectedInto<ClassB>();
Bind<IInterface>().To<ClassB>().WhenInjectedInto<ClassA>();
当它运行时,它在 ClassB 的加载方法中失败并出现此错误...
激活 IInterface 时出错 没有可用的匹配绑定,并且该类型不可自绑定。
如果我尝试以下操作...
Bind<IInterface>().To<ClassC>().WhenInjectedInto<ClassB>();
Bind<IInterface>().To<ClassB>();
它会无限循环并且永远不会创建 ClassC。
编辑 我已将其简化为一个单元测试,该测试通过但没有给出我想要的结果......
[TestClass]
public class NinjectTestFixture
{
private interface IDoSomething
{
void SaySomething();
}
private class ClassA : IDoSomething
{
public void SaySomething()
{
Console.WriteLine("Hello from Class A");
}
}
private class ClassB : IDoSomething
{
private IKernel _Kernel;
public ClassB(IKernel kernel)
{
_Kernel = kernel;
}
public void SaySomething()
{
Console.WriteLine("Hello from Class B");
var x = _Kernel.Get<IDoSomething>();
x.SaySomething();
}
}
private class ClassC
{
private IKernel _Kernel;
public ClassC(IKernel kernel)
{
_Kernel = kernel;
}
public void SaySomething()
{
Console.WriteLine("Hello from Class C");
var x = _Kernel.Get<IDoSomething>();
x.SaySomething();
}
}
[TestMethod]
public void TestMethod1()
{
var kernel = new StandardKernel();
kernel.Bind<IDoSomething>().To<ClassA>();
kernel.Bind<IDoSomething>().To<ClassB>().WhenInjectedInto<ClassC>();
kernel.Bind<ClassC>().ToSelf();
var x = kernel.Get<ClassC>();
x.SaySomething();
}
输出是: C班的你好 A班的你好,
但我想要: C班的你好 B班的你好 A班您好,
谢谢
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您没有注入到ClassC中。您正在传递内核并直接从中解析 IDoSomething。有很大的不同。
不要将内核作为参数传递 - 这样做不是依赖注入,而是服务位置(关于差异的好文章:服务定位器是一种反模式)。
将 ClassC 更改为:
您还应该对 ClassA 和 ClassB 进行相同的更改(传递您想要解析的类型/接口,而不是内核)。
You are not injecting into ClassC. You are passing in the kernel and resolving IDoSomething directly from it. There is a big difference.
Do not pass the kernel as a parameter--doing so is not Dependency Injection, it is Service Location (good article on the difference: Service Locator is an Anti-Pattern).
Change ClassC to be:
You should also make the same changes to ClassA and ClassB (pass the type/interface you want resolved, not the kernel).