【问题标题】:How to write a Service Locator Pattern where the concrete classes implements the same interface/service?如何编写服务定位器模式,其中具体类实现相同的接口/服务?
【发布时间】:2013-03-14 12:36:36
【问题描述】:

考虑以下

class ServiceA : IServiceA
    {
        public void SayHelloFromA()
        {
            Console.WriteLine("Hello Service A");
            Console.ReadKey();
        }
    }    
    class ServiceB : IServiceB{ } 
    class ServiceC : IServiceC{ }
    interface IServiceA 
    { 
        void SayHelloFromA(); 
    }
    interface IServiceB{ }
    interface IServiceC{ }

如果我想使用服务定位器模式,here 提供的示例可以完美运行。

现在说另一个类实现了如下所示的 IServiceA 接口。

class ServiceA1 : IServiceA
{
    public void SayHelloFromA()
    {
        Console.WriteLine("Hello Service A1");
        Console.ReadKey();
    }
} 

相应地,我需要将服务添加到字典中

internal ServiceLocator()    
        {        
            services = new Dictionary<object, object>();         

            this.services.Add(typeof(IServiceA), new ServiceA());
            this.services.Add(typeof(IServiceA), new ServiceA1());     
            this.services.Add(typeof(IServiceB), new ServiceB());        
            this.services.Add(typeof(IServiceC), new ServiceC());    
        } 

这是错误的,因为字典中不能存在重复的键。

那么我该如何解决这个问题呢?应该如何更改数据结构,以便服务定位器可以同时容纳两者。

注意~我正在尝试在我的工厂方法中实现服务定位器模式

public class CustomerFactory : ICustomerBaseFactory

{

          public IBaseCustomer  GetCustomer(string  CustomerType)

          { 
                   switch(CustomerType)

                   { 
                             case "1": return  new Grade1Customer(); break;

                             case "2": return new Grade2Customer(); break;

                             default:return null; 
                   } 
          } 
}

具体工厂从 IBaseCustomer

派生的位置

谢谢

【问题讨论】:

  • 您将如何检索特定的实现?服务定位器的重点是在不知道是哪个的情况下为您提供 IServiceA 的实现。在您的示例中,您将如何调用服务定位器来获得特定的实现? (假设您可以有一个带有重复项的键控容器)

标签: c# design-patterns service-locator


【解决方案1】:

您是否考虑过以嵌套在顶级字典中的具体类型为键的每个抽象类型的字典?

Dictionary<T, Dictionary<T, U>>

这样,您可以按类型查询顶级字典,然后在子字典中查询实现该类型的所有服务。

例如

var services = new Dictionary<Type, Dictionary<Type, Object>>();

现在您可以向服务字典询问类型:

services.TryGetValue(typeof(IServiceA), componentDictionary);

如果返回 true,那么您知道 componentDictionary 将包含实现该服务的组件:

foreach (c in componentDictionary.Values) {... }

通过巧妙地使用抽象基类型和泛型,您可以创建比这更强类型的解决方案。但是,这应该可以很好地工作,尽管有强制转换。

【讨论】:

  • 我已经更新了答案以进一步展示这个概念。基本上,您的服务定位器需要一个身份映射来保存/解析服务的组件。
【解决方案2】:

在 Java 中,有一个 MultiMap 类支持每个键的多个值。我相信您也可以为 C# 找到类似的数据结构。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2011-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多