我有一组get
函数的重载。每个都有不同的输入类型,但基本上是相同的签名模式(如下):
string GetPropertyValue(int propId, string defaultValue)
bool GetPropertyValue(int propId, bool defaultValue)
int GetPropertyValue(int propId, int defaultValue)
IEnumerable<string> GetPropertyValue(int propId, IEnumerable<string> defaultValues)
IEnumerable<bool> GetPropertyValue(int propId, IEnumerable<bool> defaultValues)
IEnumerable<int> GetPropertyValue(int propId, IEnumerable<int> defaultValues)
我正在努力将API简化为单个通用方法(如下所示):
T GetPropertyValue<T>(int propId , T defaultValue)
为了实现这样的方法,我尝试使用字典(inspired by this answer)来打开默认值的类型:
var actionDico = new Dictionary<Type, System.Action>
{
/* since the type of `defaultValue` is `T`, I cannot use `(bool)defaultValue` for example
therefore casting to (object) before to escape Cast operator restriction.
Will not fail as the key of the dictionary is a matching type */
{typeof(bool), () => dob.GetPropertyValue(propId, (bool)(object)defaultValue)},
{typeof(int), () => dob.GetPropertyValue(propId, (int)(object)defaultValue)},
{typeof(string), () => dob.GetPropertyValue(propId, (string)(object)defaultValue)}
}
对于具体类型,之前的实现完全没问题(至少在我的情况下)。呼叫将使用actionDico[typeof(T)]();
完成。
在字典中包含以下内容很好:
{typeof(IEnumerable<int>), () => dob.GetPropertyValue(propId, (IEnumerable<int>)(object)defaultValue)},
但是通常使用实现IEnumerable<int>
的对象(如List<int>
)来完成调用。在这种情况下,调用actionDico[typeof(T)]();
正在密钥集合中查找List<int>
,而不是IEnumerable<int>
。
我试图避免反思(并将其作为最后的手段)。是否有类似接口的Type.IsAssignableFrom(Type)
方法?换句话说,我想检查提供的类型是否实现IEnumerable<int>
而不是它。
答案 0 :(得分:1)
你无法通过这种方式查看字典中的类型。您必须遍历键值对:
Type targetType = defaultValue.GetType();
foreach (var pair in dictionary)
{
if (pair.Key.IsAssignableFrom(targetType))
{
// Use pair.Value
}
}
然而,就你如何使用它而言,在这一点上你实际上只得到了List<Tuple<Type, Action>>
而不是字典...所以你可以改用:
List<Tuple<Type, Action>> actions = new List<Tuple<Type, Action>>
{
Tuple.Create(typeof(bool), () => dob.GetPropertyValue(propId, (bool) (object)defaultValue),
Tuple.Create(typeof(int), () => dob.GetPropertyValue(propId, (int) (object)defaultValue),
// etc
};
...然后在之前的循环中使用Item1
和Item2
。
答案 1 :(得分:0)
您可以使用as operator
var isEnumerable = defaultValue as IEnumerable;
if (isEnumerable != null)
{
}