如何避免服务定位器反模式?

Pau*_*aul 13 c# dependency-injection inversion-of-control service-locator

我正在尝试从抽象基类中删除服务定位器,但我不确定要用什么来替换它.这是我所得到的一个假例子:

public abstract class MyController : Controller
{
    protected IKernel kernel;
    public MyController(IKernel kernel) { this.kernel = kernel); }

    protected void DoActions(Type[] types)
    {

        MySpecialResolver resolver = new MySpecialResolver(kernel);
        foreach(var type in types)
        {
            IMyServiceInterface instance = resolver.Get(type);
            instance.DoAction();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这个问题是派生类的instanciator不知道内核必须具有什么绑定才能防止MySpecialResolver抛出异常.

这可能是内在难以处理的,因为我从这里不知道我将要解决哪些类型.派生类负责创建types参数,但它们在任何地方都不是硬编码的.(这些类型基于派生类的组合层次结构中存在的属性.)

我试图通过延迟加载代理来解决这个问题,但到目前为止我还没有想出一个干净的解决方案.

更新

这里确实存在两个问题,一个是IoC容器被传递给控制器​​,充当服务定位器.这很容易删除 - 您可以使用各种技术在调用堆栈中向上或向下移动位置.

第二个问题是困难的问题,如果需求在运行时没有暴露,如何确保控制器具有必要的服务.它应该从一开始就很明显:你做不到!您将始终依赖于服务定位器的状态或集合的内容.在这种特殊情况下,任何数量的小问题都不会解决本文中描述的静态类型依赖关系的问题.我认为我最终要做的是将一个Lazy数组传递给控制器​​构造函数,并在缺少必需的依赖项时抛出异常.

chr*_*ris 4

也许您应该删除 Kernel、Types 和 MySpecialResolver,并让子类直接使用它们需要的 IMyServiceInterface 实例作为参数来调用 DoActions。让子类决定如何到达这些实例 - 他们应该最了解(或者万一他们不知道到底是哪个人决定需要哪些 IMyServiceInterface 实例)