创建依赖于字符串值的对象的方法有哪些?

时间:2017-02-12 23:33:22

标签: c# design-patterns

我有不同类型的提供商。该提供商提供来自不同来源的数据。此外,我在数据库中有一个表,我可以找到供特定团队使用的提供程序。

第1组 - “FirstProvider”

第2组 - “SecondProvider”等等。

根据团队的不同,我希望使用合适的提供商来获取团队的具体数据。

string providerType = ...
IProvider provider;
if(providerType == "FirstProvider") 
{
    provider = new FirstProvider();
} 
else if(providerType == "SecondProvider")
{
    provider = new FirstProvider;
}

最好的模式/方法是什么?也许有些物品出厂......

1 个答案:

答案 0 :(得分:1)

匿名构建器方法词典

在这种模式中,我们声明了一个字典:

  • 密钥是提供者名称字符串
  • 该值是一个Func对象(一个没有参数并返回IProvider类型的值的方法)
static readonly Dictionary<string, Func<IProvider>> providerBuilderMap =
    new Dictionary<string, Func<IProvider>>(StringComparer.OrdinalIgnoreCase)
{
    {"firstProviderName",()=> { return new FirstProvider(); } }
};

以上声明:

  • 声明一个readonly Dictionary对象,表示该对象是只读引用(不应更改)
  • (可选)包含StringComparer.OrdinalIgnoreCase参数,以便在敏感
  • 中设置关键比较案例
  • 根据需要使用键值对初始化词典
  • 该值是一个匿名方法,它返回一个实现IProvider
  • 的对象

我们可以使用这个字典来创建我们需要的对象:

static IProvider GetProviderUsingTypeBuilder(string name)
{
    Func<IProvider> providerBuilder = null;
    if(providerBuilderMap.TryGetValue(name, out providerBuilder))
    {
        return providerBuilder();
    }

    // Choose to throw an exception or return a null value
    //throw new ArgumentOutOfRangeException("name", "Provider not found.");
    return null;
}

类型字典

在这种模式中,我们声明了一个字典:

  • 密钥是提供者名称字符串
  • 该值只是我们需要创建的实例的Type
static readonly Dictionary<string, Type> providerTypeMap = new Dictionary<string, Type>()
{
    { "firstProviderName",typeof(FirstProvider)}
};

我们需要使用反射来创建我们需要的对象的实例。这可能比第一种模式(匿名构建器方法词典)更昂贵:

static IProvider GetProviderUsingTypeConstructor(string name)
{
    Type providerType = null;
    if (providerTypeMap.TryGetValue(name, out providerType))
    {
        var constructor = providerType.GetConstructor(Type.EmptyTypes);
        return (IProvider)constructor.Invoke(null);
    }

    //throw new ArgumentOutOfRangeException("name", "Provider not found.");
    return null;
}

请注意,在上面的方法中,我们获取并调用providerType的无参数构造函数。如果无参数构造函数不存在,则会发生运行时异常。

关于readonly Dictionary

的说明

以上示例中使用的providerBuilderMapproviderTypeMap对象是只读的。但是,Dictionary对象的元素不是只读的。如果需要,我们可以通过将声明更改为ReadOnlyDictionary来阻止添加或删除元素。例如:

using System.Collections.ObjectModel;
static readonly ReadOnlyDictionary<string, Func<IProvider>> providerBuilderMap = new ReadOnlyDictionary<string, Func<IProvider>>(
    new Dictionary<string, Func<IProvider>>(StringComparer.OrdinalIgnoreCase)
{
    {"firstProviderName",()=> { return new FirstProvider(); } }
});