使用NInject绑定通用接口,如果未设置通用类型的绑定,则使用默认接口 [英] Using NInject to bind a generic interface, with a default if a binding for the generic type is not set

查看:63
本文介绍了使用NInject绑定通用接口,如果未设置通用类型的绑定,则使用默认接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Imagine I have the following classes and interfaces:

public interface IService<T> { }

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

public class FooService : IService<Foo> { }

public class BarService : IService<Bar> { }

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

I would then like to be able to get instances from the Kernel like this:

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

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

Is it possible to setup bindings using NInject (possibly using the Conventions extension), so that I don't have to manually bind every single possible implementation of IService?

推荐答案

我最近一直在进行类似的工作,并为您的问题提出了一些更简单的解决方案(尽管有点弱).

I've been working on something similar recently and came up with somewhat simpler solution of your problem (although a bit weaker).

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

What should suffice is to bind a generic implementation (DefaultService) to the generic interface, and concrete implementations (FooService, BarService) to the concrete interfaces. When you ask for a concrete instance of the interface, Ninject resolves whether you defined the concrete binding. If you did, it gives you the appropriate instance, otherwise it falls through to the generic binding. The following code should do the trick.

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

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

The concept works throughout the whole Ninject, so you can use it along with Extensions.Conventions as well. e.g. define the following:

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>{}

使用约定来绑定服务:

kernel.Bind(x => x.FromThisAssembly()
                  .SelectAllClasses()
                  .InheritedFrom(typeof(IService<>))
                  .BindSingleInterface());

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

and create and check the appropriate services:

Assert.IsInstanceOf<BarService>(kernel.Get<IService<Bar>>());
Assert.IsInstanceOf<FooService>(kernel.Get<IService<Foo>>());
Assert.IsInstanceOf<DefaultService<Dog>>(kernel.Get<IService<Dog>>());

这篇关于使用NInject绑定通用接口,如果未设置通用类型的绑定,则使用默认接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆