Mit dynamic
Sie könnten das dynamic
Stichwort nutzen, dies zu tun, aber ich denke, es könnte für Sie zu langsam sein.
Dies ist jedoch, wie Sie es tun könnten. Dies ruft eine stark typisierte enumerate()
-Methode für List<T>
und T[]
auf, oder wenn der Wert weder eine List noch ein Array ist, ruft er die Überladung von enumerate()
auf, die nur ein Objekt aufnimmt.
Ich bin nicht ganz sicher, dass dies das ist, wonach Sie suchen, aber es gibt Ihnen eine stark typisierte Enumeration für die Listen und Arrays in Ihrer KVP-Liste.
Beachten Sie, dass gemäß Ihrer Spezifikation, berücksichtigt dies nur List und Array-Typen; andere zählbare Typen (wie Saiten, HashSet usw.) werden nicht berücksichtigt:
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();
}
}
}
explizite Reflexion Mit
Hier ist ein Weg, es zu tun Reflexion verwenden, die dynamic
vermeidet die Verwendung, die bedeutet, dass es viel schneller ist - aber wie Sie sehen können, ist es deutlich findiger!
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();
}
}
}
Wenn Sie Ihren Reflexionscode verwenden, erhalte ich einen Objektverweis, der nicht an eine Instanz eines Objekts in Zeile gesendet wird genericEnumerator = listEnumerator.MakeGenericMethod (listElemType); – BossRoss
@BossRoss Sie erhalten diesen Fehler nicht, wenn Sie meinen Beispielcode ohne Änderungen ausführen. Wenn Sie diesen Fehler erhalten, nachdem Sie den Code geändert haben, liegt das daran, dass es in der Klasse keine statische private Methode namens "enumerateList" gibt und daher "GetMethod()" null zurückgibt. Sie müssen diesen Aufruf ändern, um den entsprechenden Methodennamen und die Bindungsflags für die Methode anzugeben, die Sie aufrufen möchten. –
Ich habe den Reflexionscode verwendet, es funktioniert gut (wenn die richtigen Methoden statisch sind) Danke für die Hilfe und die gute Antwort – BossRoss