0

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

如果您有兴趣,请查看整个代码

我遇到的问题,我正在努力做到这一点,如果服务实例已经注册,注册失败,我这样做是这样的:

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

我没有做 alist.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- 我该怎么做?- 如果我将设置器设为私有,我无法在任何地方设置它,如果我在NotifyHasBeenRegistered()内部提出IService相同的问题,外人可能会调用它并导致问题。

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

谢谢你的帮助。

4

1 回答 1

1

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

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

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

NGenerics 提供了跳过列表和其他一些有用的数据结构的实现:https ://github.com/nenerics/nenerics

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

于 2013-11-12T12:25:01.580 回答