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

时间:2015-03-11 12:16:13

标签: dependency-injection ninject inversion-of-control

我有一个通用接口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)的方法中实现的,并根据来自数据库的一些数据选择正确的具体类。

我现在需要在控制器类中进行构造函数注入,并希望配置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动态提供具体实例?到目前为止,我只使用构造函数注入。

1 个答案:

答案 0 :(得分:2)

我认为你不应该污染&#39;您的DI配置。而是通过使用可以将RequestData消息分派到正确的处理程序实现的代理类来解决此问题:

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课程绑定到IService,并允许将其注入依赖IService的任何人。调度程序将确保将请求分派给正确的实现。

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