我有不同类型的提供商。该提供商提供来自不同来源的数据。此外,我在数据库中有一个表,我可以找到供特定团队使用的提供程序。
第1组 - “FirstProvider”
第2组 - “SecondProvider”等等。
根据团队的不同,我希望使用合适的提供商来获取团队的具体数据。
string providerType = ...
IProvider provider;
if(providerType == "FirstProvider")
{
provider = new FirstProvider();
}
else if(providerType == "SecondProvider")
{
provider = new FirstProvider;
}
最好的模式/方法是什么?也许有些物品出厂......
答案 0 :(得分:1)
在这种模式中,我们声明了一个字典:
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
以上示例中使用的providerBuilderMap
和providerTypeMap
对象是只读的。但是,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(); } }
});