服务定位器 - 一种识别服务是否已注册的“安全”方法



我正在开发一个服务定位器系统,服务可以在代码库周围注册并得到请求。

如果您有兴趣,可以查看整个代码。

遇到的问题,我正在尝试使它,以便如果服务实例已经注册,注册失败,我这样做:

/// <summary>
/// Registers a service.
/// More than one instance of a service type is allowed.
/// Registration will fail if the same instance has already registered itself.
/// </summary>
public static void Register(IService service)
{
    Type type = service.GetType();
    List<IService> list = GetServiceList(type, out list);
    if (list.IsEmpty())
        dic[type] = list;
    else if (list.Contains(service))
        throw new RegistrationException("[Vervices]: Service instance: `" + service + "` has already registered!");
    else if (list.FirstOrDefault(s => s.Identifier == service.Identifier) != null)
        throw new RegistrationException("[Vervices]: There already exist a service instance of id: `" + service.Identifier);
    list.Add(service);
    if (service is MonoBehaviour)
        Object.DontDestroyOnLoad(service as MonoBehaviour);
}

与其做一个list.Contains(service)我想为什么不让每个服务都有一个HasRegistered - 当我注册一个服务时,我将其设置为 true。现在界面将如下所示:

public interface IService
{
    void Ping(Object sender);
    string Identifier { get; }
    bool HasRegistered { get; set; }
}

现在我可以只做if (service.HasRegistered) throw exception;而不是if (list.Contains(service) throw exception;

但问题是,这并不安全。该物业既有公共二传手,也有吸引人,这意味着任何外人都可以进来做service.HasRegistered = false; !!!

它应该设置为 true,仅在 Register 内部 - 我该怎么做? - 如果我将二传手设为私有,我无法在任何地方设置它,如果我在同一个问题IService内部进行NotifyHasBeenRegistered(),外人可能会调用它并引起问题。

我怎样才能以安全的方式做我想做的事?

感谢您的帮助。

就个人而言,我会坚持Contains方法,原因有两个:

  • 定位器应负责了解已注册的服务,而不是服务(单一责任原则)。
  • 使服务无法设置属性的唯一方法是对只有定位器可以设置的internal属性使用继承。同样,强制服务继承基类是非常严格的(因为 c# 不支持多重继承)。

如果您担心Contains性能,则可以使用性能优于List<T>的数据结构。"跳过列表"是一种具有类似于二叉搜索树的属性的列表。它允许您在 O(log n) 时间内搜索特定项目,而List<T>需要 O(n) 时间(即慢得多)。

NGenerics 提供了 Skip 列表和其他几种有用的数据结构的实现: https://github.com/ngenerics/ngenerics

以下是数据结构性能的备忘单: http://bigocheatsheet.com/#data-structures

相关内容

  • 没有找到相关文章

最新更新