说我有一个这样的方法:
public void Foo(object arguments)
Run Code Online (Sandbox Code Playgroud)
并说我需要检测的类型arguments是否实际上是枚举。我会这样写:
if (arguments is IEnumerable)
Run Code Online (Sandbox Code Playgroud)
现在,假设我需要检测它是否是KeyValuePair的枚举(无论键的类型和值的类型如何)。我的直觉是写这样的东西:
if (arguments is IEnumerable<KeyValuePair<,>>)
Run Code Online (Sandbox Code Playgroud)
但是视觉工作室抱怨到Using the generic type 'KeyValuePair<TKey, TValue>' requires 2 type arguments。
我也尝试过:
if (arguments is IEnumerable<KeyValuePair<object, object>>)
Run Code Online (Sandbox Code Playgroud)
但如果键不是对象(例如string,例如)或值是对象(例如int,例如),则返回false 。
有人建议我如何确定枚举是否包含KeyValuePair,而与键类型和值类型无关,如果是,我如何遍历这些对?
这里你需要一些反思:
Boolean isKeyValuePair = false;
Type type = arguments.GetType();
if (type.IsGenericType)
{
Type[] genericTypes = type.GetGenericArguments();
if (genericTypes.Length == 1)
{
Type underlyingType = genericTypes[0];
if (underlyingType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
isKeyValuePair = true;
}
}
Run Code Online (Sandbox Code Playgroud)
为了重建Enumerable并迭代它,您可以使用以下方法dynamic:
List<KeyValuePair<Object, Object>> list = new List<KeyValuePair<Object, Object>>();
foreach (dynamic kvp in (IEnumerable)arguments)
list.Add(new KeyValuePair<Object, Object>(kvp.Key, kvp.Value));
Run Code Online (Sandbox Code Playgroud)
或者,与LINQ:
List<KeyValuePair<Object, Object>> list = (from dynamic kvp in (IEnumerable)arguments select new KeyValuePair<Object, Object>(kvp.Key, kvp.Value)).ToList();
Run Code Online (Sandbox Code Playgroud)
我还找到了另一种解决方案,但这纯粹是疯狂的:
Boolean isKeyValuePair = false;
Type type = arguments.GetType();
if (type.IsGenericType)
{
Type[] genericTypes = type.GetGenericArguments();
if (genericTypes.Length == 1)
{
Type underlyingType = genericTypes[0];
if (underlyingType.GetGenericTypeDefinition() == typeof (KeyValuePair<,>))
{
Type[] kvpTypes = underlyingType.GetGenericArguments();
Type kvpType = typeof(KeyValuePair<,>);
kvpType = kvpType.MakeGenericType(kvpTypes);
Type listType = typeof (List<>);
listType = listType.MakeGenericType(kvpType);
dynamic list = Activator.CreateInstance(listType);
foreach (dynamic argument in (IEnumerable)arguments)
list.Add(Activator.CreateInstance(kvpType, argument.Key, argument.Value));
}
}
}
Run Code Online (Sandbox Code Playgroud)
参考: