使用 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();
}
}
}
GetMethod()
返回 null。你需要更改该调用以指定适当的方法名称和绑定标志,以便调用所需的方法。 - Matthew Watson