如何避免服务定位器反模式? [英] How to avoid Service Locator Anti-Pattern?

查看:93
本文介绍了如何避免服务定位器反模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从抽象基类中删除服务定位器,但是我不知道该怎么替换它。这是一个有趣的例子:

I'm trying to remove a Service Locator from an abstract base class, but I'm not sure what to replace it with. Here is a psuedo-example of what I've got:

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();
        }
    }
}

这个问题是派生类的instanciator不知道内核必须绑定什么为了保持 MySpecialResolver 不会引发异常。

The problem with this is that the instanciator of a derived class doesn't know what bindings the kernel must have in order to keep MySpecialResolver from throwing an exception.

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

This might be intrinsicly intractable because I don't know from here which types I'll have to resolve. The derived classes are responsible for creating the types parameter, but they aren't hardcoded anywhere. (The types are based on the presence of attributes deep within the derived class's composition hierarchy.)

我试图用懒惰加载代理来解决这个问题,但到目前为止没有提出一个干净的解决方案。

I've trying to fix this with lazy loading delegates, but so far I haven't come up with a clean solution.

这里真的有两个问题,一个是将IoC容器传递给控制器​​,充当服务定位器。这很容易删除 - 您可以使用各种技巧向上或向下移动位置。

There are really two issues here, one is that the IoC container is passed to the controller, acting as a service locator. This is easy to remove--you can move the location up or down the call stack using all sorts of techniques.

第二个问题是困难的,你怎么能确保控制器在需求在运行时不暴露时具有必要的服务。从一开始应该是显而易见的:你不能!您将始终依赖于服务定位器的状态或集合的内容。在这种特殊情况下,无需解决这篇文章中描述的问题, a>具有静态类型的依赖关系。我想我最终会做的是将一个Lazy数组传递给控制器​​构造函数,如果缺少必需的依赖关系,则抛出异常。

The second issue is the difficult one, how can you ensure that the controller has the necessary services when the requirements aren't exposed until runtime. It should have been obvious from the start: you can't! You will always be dependent upon either the state of the service locator or contents of a collection. In this particular case no amount of fiddling will ever resolve the problem described in this article with staticly typed dependencies. I think that what I'm going to end up doing is passing a Lazy array into the controller constructor and throwing an exception if a required dependency is missing.

推荐答案

也许你应该删除内核,类型和MySpecialResolver,让子类直接用它们需要的IMyServiceInterface实例调用DoActions。并让子类决定他们如何获得这些实例 - 他们应该知道最好(或者如果他们不知道谁决定需要哪个IMyServiceInterface的实体)

Maybe you should just do away the Kernel, Types and MySpecialResolver and let the subclasses call DoActions with the IMyServiceInterface instances they need as argument directly. And let the subclasses decide how they get to these instances - they should know best (or in case they don't know which exactly the one who ever decides which instances of IMyServiceInterface are needed)

这篇关于如何避免服务定位器反模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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