如何在没有条件/上下文DI的情况下将不同的实现注入到同一个接口?

时间:2017-04-14 20:09:46

标签: c# dependency-injection

我有以下问题,我目前有一个使用条件依赖注入的解决方案。我已经读到这是一个坏主意,例如SimpleInjector文档中的here。我现在已经阅读了很多帖子,并且已经看到了各种建议使用策略,工厂模式等的东西。我真正想要的是一些细节 - 即一些代码的例子 - 关于如何在没有条件注入的情况下解决。我需要更多的东西"使用工厂"。这是我的代码的简化版本。这是一个MVC Web应用程序,因此是控制器。

public abstract class QAControllerBase : Controller
{
    protected readonly QABusinessLayer _blQA;
    public QAControllerBase(QABusinessLayer bl) 
    {
        _blQA = bl;
    }

    [HttpGet]
    public ActionResult PPR(string accession, string site)
    {
        var m = _blQA.popPPRViewModel(accession);

        return View(m);
    }
}

public class QASouthController : QAControllerBase
{

    public QASouthController([QASouthBinding] QABusinessLayer bl) : base(bl)
    {

    }

    // some actions that are specific to South
}


public class QANorthController : QAControllerBase
{

    public QANorthController([QANorthBinding] QABusinessLayer bl) : base(bl)
    {

    }

    // some actions that are specific to North
}

public abstract class QABusinessLayer
{
    protected readonly IFullBaseRepo _repo;
    public QABusinessLayer(IFullBaseRepo repo)
    {
        _repo = repo;
    }

    public abstract PPRViewModel popPPRViewModel(string accession);

    protected PPRViewModel DoSomeCommonStuff(PPRViewModel model)
    {
        ...
        return model;
    }

}

public class SouthBusinessLayer: QABusinessLayer
{

    public SouthBusinessLayer([QASouthBinding] IFullBaseRepo repo) : base(repo)
    {

    }

    public override PPRViewModel popPPRViewModel(string accession)
    {
        var m = new PPRViewModel();
        // do some stuff that is specific to South
        DoSomeCommonStuff(m);

        return m;
    }
}

public class NorthBusinessLayer : QABusinessLayer
{


    public NorthBusinessLayer([QANorthBinding] IFullBaseRepo repo) : base(repo)
    {

    }
    public override PPRViewModel popPPRViewModel(string accession)
    {
        var m = new PPRViewModel();
        // do some stuff that is specific to North
        DoSomeCommonStuff(m);

        return m;
    }
}

以下是与之相关的Ninject绑定代码:

            kernel.Bind<QABusinessLayer>()
            .To<SouthBusinessLayer>()
            .WhenTargetHas<QASouthBinding>()
            .InRequestScope();

        kernel.Bind<QABusinessLayer>()
            .To<NorthBusinessLayer>()
            .WhenTargetHas<QANorthBinding>()
            .InRequestScope();

QASouthBinding和QANorthBinding只是简单的属性。我不是要求Ninject的具体例子。关于如何在不使用条件或基于上下文的注入的情况下处理此问题的任何代码示例。

1 个答案:

答案 0 :(得分:1)

使您的QABusinessLayer类抽象化。

将您的启动配置更改为:

For each job
From a table of jobs and persons
    Where not exits
        For each person
            Get jobs of each person

            Minus   

            Get the skills of job

        Remove appropriate person

更改您的控制器构造函数以接受具体的业务层类型:

kernel
    .Bind<SouthBusinessLayer>()
    .To<SouthBusinessLayer>()
    .InRequestScope();

kernel
    .Bind<NorthBusinessLayer>()
    .To<NorthBusinessLayer>()
    .InRequestScope();

少数事情:

  1. 如果Ninject将具体类型自动绑定到同一类型,则无需在启动期间手动配置依赖项。
  2. 您可能希望使用界面而不是仅传递具体的BusinessLayer类型。