2

我有一个用于保存 Web 服务访问的连接配置信息的接口:

public interface IServiceConnectionConfiguration
{
    string Username { get; }
    string Password { get; }
    string ChannelEndpointUrl { get; }
    string MediaEndpointUrl { get; }
    string PlayerlEndpointUrl { get; }
    string PlaylistEndpointUrl { get; }
}

我有一个工厂类,它返回特定于所请求服务类型的服务实例。

public static class ServiceClientFactory
{
    public static void Configure(IServiceConnectionConfiguration config)
    {
        _config = config;
    }
    public static T GetService<T>() where T : class, IServiceClient
    {
    }
}

该工厂被称为

Channel channelService   = factory.GetService<Channel>();

我想弄清楚的是工厂代码根据初始化期间传递的配置对象解析传入类型本身的端点 url 的一种优雅方式。例如。如果传递的类型参数是channel,则在构造ChannelService时应该取ChannelEndpointUrl。

我考虑过在配置类上使用属性来用它们对应的服务类型来装饰端点 url,但这似乎是一个糟糕的设计。

有任何想法吗。

4

1 回答 1

3

好吧,解决它的一种方法是让工厂有一个包含初始化逻辑的私有静态字典,由“类型”索引。类似于策略模式。

例如:

public static class ServiceClientFactory
{
    private static IServiceConnectionConfiguration _config;
    private static readonly Dictionary<Type, Func<IServiceClient>> Initializers = new Dictionary<Type, Func<IServiceClient>>();

    static ServiceClientFactory()
    {
        Initializers.Add(typeof(Channel), () =>
                                               {
                                                   return //create the service client based on the endpoint
                                               });
    }

    public static void Configure(IServiceConnectionConfiguration config)
    {
        _config = config;
    }

    public static T GetService<T>() where T : class, IServiceClient
    {
        return (T)Initializers[typeof (T)]();
    }
}

编辑:现在,正如您所提到的,您不能在工厂中显式实例化,因为您会导致循环引用,也许您可​​以强制使用 new() 约束,并在 GetService 方法中构造实例,并且只使用字典作为端点配置,例如:

public static class ServiceClientFactory
{
    private static IServiceConnectionConfiguration _config;
    private static readonly Dictionary<Type, Action<IServiceClient>> Initializers = new Dictionary<Type, Action<IServiceClient>>();

    static ServiceClientFactory()
    {
        Initializers.Add(typeof(Channel), t =>
                                              {
                                                  t.Url = _config.ChannelEndpointUrl;
                                                  //configure t using the appropriate endpoint
                                              });
    }

    public static void Configure(IServiceConnectionConfiguration config)
    {
        _config = config;
    }

    public static T GetService<T>() where T : class, IServiceClient, new()
    {
        var service = new T();
        Initializers[typeof(T)](service);
        return service;
    }
}
于 2012-06-01T05:43:16.670 回答