如何在不知道键的类型和值的类型的情况下遍历KeyValuePair的枚举

des*_*lsj 5 c#

说我有一个这样的方法:

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,而与键类型和值类型无关,如果是,我如何遍历这些对?

Tom*_*zzo 3

这里你需要一些反思:

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)

参考: