使用NInject绑定通用接口,如果未设置泛型类型的绑定,则使用默认值

cbp*_*cbp 10 ninject

想象一下,我有以下类和接口:

public interface IService<T> { }

public class DefaultService<T> : IService<T> { }

public class FooService : IService<Foo> { }

public class BarService : IService<Bar> { }
Run Code Online (Sandbox Code Playgroud)

我希望能够像这样从内核中获取实例:

Kernel.Get<IService<Foo>>();  // Should return FooService
Kernel.Get<IService<Bar>>();  // Should return BarService
Kernel.Get<IService<Dog>>();  // Should return DefaultService
Kernel.Get<IService<Cat>>();  // Should return DefaultService
Kernel.Get<IService<Giraffe>>();  // Should return DefaultService
Run Code Online (Sandbox Code Playgroud)

是否可以使用NInject设置绑定(可能使用约定扩展),这样我就不必手动绑定IService的每个可能的实现?

Jan*_*Jan 11

我最近一直在做类似的事情,并提出了一些更简单的问题解决方案(虽然有点弱).

什么应该足够的是将通用实现(DefaultService)绑定到通用接口,并将具体实现(FooService,BarService)绑定到具体接口.当您要求接口的具体实例时,Ninject会解决您是否定义了具体绑定.如果你这样做,它会为你提供适当的实例,否则它会落到通用绑定中.以下代码应该可以解决问题.

var kernel = new StandardKernel();
kernel.Bind(typeof(IService<>)).To(typeof(DefaultService<>));
kernel.Bind<IService<Foo>>().To<FooService>();
kernel.Bind<IService<Bar>>().To<BarService>();
Run Code Online (Sandbox Code Playgroud)

编辑:

这个概念适用于整个Ninject,因此您可以将它与Extensions.Conventions一起使用.例如,定义以下内容:

public class Foo{}
public class Bar{}
public class Dog{}

public interface IService<T>{}
public class DefaultService<T> : IService<T>{}
public class FooService : IService<Foo>{}
public class BarService : IService<Bar>{}
Run Code Online (Sandbox Code Playgroud)

使用约定来绑定服务:

kernel.Bind(x => x.FromThisAssembly()
                  .SelectAllClasses()
                  .InheritedFrom(typeof(IService<>))
                  .BindSingleInterface());
Run Code Online (Sandbox Code Playgroud)

并创建和检查适当的服务:

Assert.IsInstanceOf<BarService>(kernel.Get<IService<Bar>>());
Assert.IsInstanceOf<FooService>(kernel.Get<IService<Foo>>());
Assert.IsInstanceOf<DefaultService<Dog>>(kernel.Get<IService<Dog>>());
Run Code Online (Sandbox Code Playgroud)