c# - 作为服务定位器的通用静态类

标签 c# oop design-patterns static monogame

我将服务定位器模式应用为 described in Game Programming模式,并且想知道可能的通用实现。以下代码确实工作,但我对使用通用和静态的类感到困惑。

以下 C# 代码的想法是为应用程序的其他部分提供“全局”服务,仅公开接口(interface)而不是完整的实现。使用此方法注册的每个服务在应用程序中只有一个实例,但我希望能够轻松地换入/换出所提供接口(interface)的不同实现。

我的问题是:当我使用以下类在整个应用程序中提供不同的服务时,C# 如何知道我引用的是不同类型的不同服务?直觉上,我几乎认为静态变量 _service 会被每个新服务覆盖。

public static class ServiceLocator<T>
{
    static T _service;

    public static T GetService()
    {
        return _service;
    }

    public static void Provide(T service)
    {
        _service = service;
    }
}

这里有一些用法:

// Elsewhere, providing:
_camera = new Camera(GraphicsDevice.Viewport);
ServiceLocator<ICamera>.Provide(_camera);

// Elsewhere, usage:
ICamera camera = ServiceLocator<ICamera>.GetService();

// Elsewhere, providing a different service:
CurrentMap = Map.Create(strategy);
ServiceLocator<IMap>.Provide(CurrentMap);

// Elsewhere, using this different service:
IMap map = ServiceLocator<IMap>.GetService();

最佳答案

C# 为开放类型的泛型参数的每个组合创建一个单独的封闭类型。
由于泛型参数的每个组合都会创建一个单独的类,因此调用静态构造函数并为每个参数创建自己的成员。 您可以将它们视为不同的类别。

public static class GenericCounter<T>
{
    public static int Count { get; set; } = 0;
}

GenericCounter<int>.Count++;
GenericCounter<int>.Count++;
GenericCounter<string>.Count++;
Console.WriteLine(GenericCounter<double>.Count); // 0
Console.WriteLine(GenericCounter<int>.Count); // 2
Console.WriteLine(GenericCounter<string>.Count); // 1

此代码输出:

0
2
1

例如,在您的情况下,行为将与您创建两个单独的类相同:

public static class ServiceLocatorOfIMap
{
    static IMap _service;

    public static IMap GetService()
    {
        return _service;
    }

    public static void Provide(IMap service)
    {
        _service = service;
    }
}

public static class ServiceLocatorOfICamera 
{
    static ICamera _service;

    public static ICamera GetService()
    {
        return _service;
    }

    public static void Provide(ICamera service)
    {
        _service = service;
    }
}

并像这样使用它:

// Elsewhere, providing:
_camera = new Camera(GraphicsDevice.Viewport);
ServiceLocatorForICamera.Provide(_camera);

// Elsewhere, usage:
ICamera camera = ServiceLocatorForICamera.GetService();

// Elsewhere, providing a different service:
CurrentMap = Map.Create(strategy);
ServiceLocatorForIMap.Provide(CurrentMap);

// Elsewhere, using this different service:
IMap map = ServiceLocatorForIMap.GetService();

总的来说,这和C#遇到静态泛型类时的做法类似。

关于c# - 作为服务定位器的通用静态类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44911713/

相关文章:

javascript - Javascript 回调模式示例 - 它真的更高效吗?

java - 使用工厂模式的主要目的?

php - 使用复合模式限制可以相互添加的对象类型

c# - Microsoft Edge 未使用激活的 Windows 身份验证加载 CSS 文件

c# - 让 SqlBulkCopy 在 MiniProfiler 中显示为 sql

java - 如何制作预设的唯一类对象

c++ - 如何获取对象的常量引用并使用该引用更改对象(使用 const_cast)?

python - 如何将部分函数绑定(bind)为 Python 类实例上的方法

c# - 在datagridview中垂直显示所有单元格文本

c# - 在 ASP.NET MVC 5 启动类中注入(inject)依赖项