如何使用自定义逻辑将泛型类型与继承绑定?

How do I bind generic types with inheritance using custom logic?

我有一个通用接口IService,具体实现了三四个。

public interface IService {
   void HandleRequest( RequestData data );
}

public class AService : IService {
   public void HandleRequest( RequestData data ) {
   }
}

public class BService : IService {
   public void HandleRequest( RequestData data ) {
   }
}

选择具体实施与不同实施的规则实际上已实施到分析输入对象 (RequestData) 的方法中,并根据来自数据库的一些数据选择正确的具体 class.

我现在需要在控制器中进行构造函数注入 class 并希望配置 Ninject 来处理这些对象的实例创建,就像下面的示例

public class MyController : ApiController
{
    private readonly IService _service;

    public MyController( IService service ) {
        _service = service;
    }
}

有没有办法写出这样的扩展来支持Ninject决策过程?我在想这样的事情

Bind<IService>().To<AService>().IfConditionIsTrue( new CustomProvider() );
Bind<IService>().To<BService>().IfConditionIsTrue( new CustomProvider() );

public class CustomProvider {
    public bool ApplyCustomLogic() {
        RequestData rd = GetParameter();
        [...]
        //custom logic implementation here..
    }
}

此外,如何利用 ninject 功能即时创建实例?比如某个时候某个方法里面,我需要一个IService的实例。我如何要求 ninject 即时提供具体实例?到目前为止,我只使用构造函数注入。

我认为您不应该 'pollute' 您的 DI 配置。而是使用可以将 RequestData 消息发送到正确的处理程序实现的代理 class 来解决此问题:

public sealed class ServiceDispatcher : IService
{
    private readonly Kernel kernel;
    public ServiceDispatcher(Kernel kernel) {
        this.kernel = kernel;
    }

    public void HandleRequest(RequestData data) {
        Type implementationType;
        // custom logic to determine correct IService based on data here..
        // and resolve that implementation from the kernel.
        IService realService = (IService)this.kernel.Get(implementationType);
        realService.HandleRequest(data);
    }
}

现在您可以将您的 ServiceDispatcher class 绑定到 IService 并允许它注入任何依赖 IService 的人。调度程序将确保将请求调度到正确的实现。

但您可能要考虑使用通用抽象,例如 IService<T>。例如看一下this article