我刚刚开始在我的ASP.NET MVC 3应用程序中使用Ninject(v2.2.0.0)。到目前为止,我很高兴,但我遇到了一个我似乎无法弄清楚的情况。
我想要做的是将接口绑定到具体的实现,让Ninject能够使用工厂将具体实现注入到构造函数中(也将在Ninject中注册)。问题是我希望我的构造函数引用具体类型,而不是接口。
以下是一个例子:
public class SomeInterfaceFactory<T> where T: ISomeInterface, new()
{
public T CreateInstance()
{
// Activation and initialization logic here
}
}
public interface ISomeInterface
{
}
public class SomeImplementationA : ISomeInterface
{
public string PropertyA { get; set; }
}
public class SomeImplementationB : ISomeInterface
{
public string PropertyB { get; set; }
}
public class Foo
{
public Foo(SomeImplementationA implA)
{
Console.WriteLine(implA.PropertyA);
}
}
public class Bar
{
public Bar(SomeImplementationB implB)
{
Console.WriteLine(implB.PropertyB);
}
}
在其他地方,我想只使用界面进行绑定:
kernel.Bind<Foo>().ToSelf();
kernel.Bind<Bar>().ToSelf();
kernel.Bind(typeof(SomeInterfaceFactory<>)).ToSelf();
kernel.Bind<ISomeInterface>().To ...something that will create and use the factory
然后,当从Ninject请求Foo实例时,它会看到其中一个构造函数参数实现了绑定接口,获取工厂,并实例化了正确的具体类型(SomeImplementationA)并将其传递给Foo的构造函数。
这背后的原因是我将有许多ISomeInterface的实现,我宁愿避免必须单独绑定每个。其中一些实现可能在编译时是未知的。
我尝试使用:
kernel.Bind<ISomeInterface>().ToProvider<SomeProvider>();
提供程序根据请求的服务类型检索工厂,然后调用其CreateInstance方法,返回具体类型:
public class SomeProvider : Provider<ISomeInterface>
{
protected override ISomeInterface CreateInstance(IContext context)
{
var factory = context.Kernel.Get(typeof(SomeInterfaceFactory<>)
.MakeGenericType(context.Request.Service));
var method = factory.GetType().GetMethod("CreateInstance");
return (ISomeInterface)method.Invoke();
}
}
但是,我的提供者从未被调用过。
我很好奇Ninject是否可以支持这种情况,如果是的话,我可以如何解决这个问题。
我希望这足以说明我的情况。如果我需要进一步说明,请告诉我。
谢谢!
答案 0 :(得分:1)
似乎你误解了ninject是如何工作的。如果您创建Foo,它会看到它需要SomeImplementationA
并尝试为它创建一个实例。因此,您需要为SomeImplementationA
而不是ISomeInterface
定义绑定。
也很可能你的实现打破了依赖倒置原则,因为你依赖于具体实例而不是抽象。
一次注册所有类似类型的解决方案(以及配置IoC容器的首选方法)是按约定使用配置。请参阅Ninject.Extensions.Conventions extenstion。