使用dynamic
你可以充分利用dynamic
關鍵字做到這一點,但我認爲這可能是你太慢了。
但是,這是你如何做到的。這將爲List<T>
和T[]
調用強類型的enumerate()
方法,或者如果該值既不是列表也不是數組,它將調用enumerate()
的過載,該過載只需要一個對象。
我並不完全確定這是你之後的事情,但它確實爲您提供了KVP列表中列表和陣列的強類型枚舉。
請注意,根據您的規範,這隻考慮列表和數組類型;其他枚舉類型(如字符串,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();
}
}
}
當使用你的反射代碼時,我得到一個對象引用沒有發送到 上的一個對象實例genericEnumerator = listEnumerator.MakeGenericMethod(listElemType); – BossRoss
@BossRoss當你沒有任何改變的情況下運行我的示例代碼時,你不會得到那個錯誤。如果在更改代碼時發生錯誤,這是因爲在類中沒有稱爲「enumerateList」的靜態私有方法,因此'GetMethod()'返回null。您將需要更改該調用,以便爲要調用的方法指定適當的方法名稱和綁定標誌。 –
我已經使用了反射代碼,它運作良好(當正確的方法是靜態的)謝謝你的幫助和良好的答案 – BossRoss