使用Ninject将接口绑定到编译时未知的多个实现

时间:2011-11-25 23:09:30

标签: ninject

我刚刚开始在我的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是否可以支持这种情况,如果是的话,我可以如何解决这个问题。

我希望这足以说明我的情况。如果我需要进一步说明,请告诉我。

谢谢!

1 个答案:

答案 0 :(得分:1)

似乎你误解了ninject是如何工作的。如果您创建Foo,它会看到它需要SomeImplementationA并尝试为它创建一个实例。因此,您需要为SomeImplementationA而不是ISomeInterface定义绑定。

也很可能你的实现打破了依赖倒置原则,因为你依赖于具体实例而不是抽象。

一次注册所有类似类型的解决方案(以及配置IoC容器的首选方法)是按约定使用配置。请参阅Ninject.Extensions.Conventions extenstion。