首页 文章

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

提问于
浏览
2

我刚刚开始在我的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 回答

  • 1

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

    最有可能的是,您的实现会破坏依赖性倒置原则,因为您依赖于具体实例而不是抽象 .

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

相关问题