使用dynamic
您可以利用 dynamic 关键字来执行此操作,但我认为这对您来说可能太慢了。
但是,您可以这样做。这将为List<T> 和T[] 调用强类型enumerate() 方法,或者如果值既不是List 也不是数组,它将调用enumerate() 的重载,它只接受一个对象。
我不完全确定这是您所追求的,但它确实为您提供了 KVP 列表中列表和数组的强类型枚举。
请注意,根据您的规范,这仅考虑 List 和 Array 类型;其他可枚举类型(如字符串、HashSet等)不予考虑:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
sealed class Program
{
void test()
{
List<KeyValuePair<string, object>> lKVP = new List<KeyValuePair<string, object>>();
List<string> lS = new List<string> { "s1", "s2" };
string[] aS = {"a1", "a2"};
lKVP.Add(new KeyValuePair<string, object>("String", "E92D8719-38A6-0000-961F-0E66FCB0A363"));
lKVP.Add(new KeyValuePair<string, object>("Test", lS));
lKVP.Add(new KeyValuePair<string, object>("IntNotEnumerable", 12345));
lKVP.Add(new KeyValuePair<string, object>("Array", aS));
foreach (KeyValuePair<string,object> kvp in lKVP)
{
enumerate((dynamic) kvp.Value);
}
}
static void enumerate<T>(List<T> list)
{
Console.WriteLine("Enumerating list of " + typeof(T).FullName);
foreach (var item in list)
Console.WriteLine(item);
Console.WriteLine();
}
static void enumerate<T>(T[] array)
{
Console.WriteLine("Enumerating array of " + typeof(T).FullName);
foreach (var item in array)
Console.WriteLine(item);
Console.WriteLine();
}
static void enumerate(object obj)
{
Console.WriteLine("Not enumerating type " + obj.GetType().FullName + " with value " + obj);
Console.WriteLine();
}
static void Main(string[] args)
{
new Program().test();
}
}
}
使用显式反射
这是一种使用反射的方法,避免使用dynamic,这意味着它要快得多 - 但正如您所见,它要复杂得多!
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
namespace ConsoleApp1
{
sealed class Program
{
void test()
{
List<KeyValuePair<string, object>> lKVP = new List<KeyValuePair<string, object>>();
List<string> lS = new List<string> { "s1", "s2" };
string[] aS = {"a1", "a2"};
lKVP.Add(new KeyValuePair<string, object>("String", "E92D8719-38A6-0000-961F-0E66FCB0A363"));
lKVP.Add(new KeyValuePair<string, object>("Test", lS));
lKVP.Add(new KeyValuePair<string, object>("IntNotEnumerable", 12345));
lKVP.Add(new KeyValuePair<string, object>("Array", aS));
var listEnumerator = this.GetType().GetMethod("enumerateList", BindingFlags.NonPublic | BindingFlags.Static);
var arrayEnumerator = this.GetType().GetMethod("enumerateArray", BindingFlags.NonPublic | BindingFlags.Static);
foreach (KeyValuePair<string, object> kvp in lKVP)
{
MethodInfo genericEnumerator = null;
var arrayElemType = arrayElementType(kvp.Value);
if (arrayElemType != null)
{
genericEnumerator = arrayEnumerator.MakeGenericMethod(arrayElemType);
}
else
{
var listElemType = listElementType(kvp.Value);
if (listElemType != null)
genericEnumerator = listEnumerator.MakeGenericMethod(listElemType);
}
if (genericEnumerator != null)
genericEnumerator.Invoke(null, new[] { kvp.Value });
else
Console.WriteLine("Not enumerating type: " + kvp.Value.GetType().FullName + "\n");
}
}
static Type arrayElementType(object sequence)
{
if (sequence is IEnumerable)
{
var type = sequence.GetType();
if (type.IsArray)
return type.GetElementType();
}
return null;
}
static Type listElementType(object sequence)
{
if (sequence is IEnumerable)
{
var type = sequence.GetType();
if (typeof(IList).IsAssignableFrom(type) && type.IsGenericType)
return type.GetProperty("Item").PropertyType;
}
return null;
}
static void enumerateList<T>(List<T> list)
{
Console.WriteLine("Enumerating list of " + typeof(T).FullName);
foreach (var item in list)
Console.WriteLine(item);
Console.WriteLine();
}
static void enumerateArray<T>(T[] array)
{
Console.WriteLine("Enumerating array of " + typeof(T).FullName);
foreach (var item in array)
Console.WriteLine(item);
Console.WriteLine();
}
static void Main(string[] args)
{
new Program().test();
}
}
}