2014-04-08 31 views
9

ich eine Art Deserialisierung bin die Umsetzung und kämpfte mit einem Problem:Convert Liste <object> zu <Type> Liste Typ wird zur Laufzeit bekannt

Ich habe List<object> und System.Reflection.Field, es ist FieldType kann List<string>, List<int> oder List<bool>, so dass ich sein müssen von List<object> zu diesen Typen konvertieren.

public static object ConvertList(List<object> value, Type type) 
{ 
    //type may be List<int>, List<bool>, List<string> 
} 

Ich kann jeden Fall separat schreiben, aber es sollte einen besseren Weg mit Reflexion geben.

Antwort

7

ich zu gehen glauben, was Sie wollen, ist :

public static object ConvertList(List<object> value, Type type) 
{ 
    var containedType = type.GenericTypeArguments.First(); 
    return value.Select(item => Convert.ChangeType(item, containedType)); 
} 

Beispiel Nutzung:

var objects = new List<Object> { 1, 2, 3, 4 }; 

ConvertList(objects, typeof(List<int>)).Dump(); 

Ich bin nicht sicher, wie nützlich diese allerdings ist ... Es ist die irrsinnig nützlich Convert.ChangeType Methode unterstreicht Ich denke!

+0

Ihre Methode gibt eine IEnumerable nicht eine Liste zurück. Ich habe die Frage vielleicht falsch verstanden. – Guillaume

0

Try this:

public static List<T> ConvertList<T>(List<object> list) 
{ 
    List<T> castedList = list.Select(x => (T)x); 
    return castedList; 
} 

Call:

List<object> myList = new List<object> {"test", "foo", "bar"}; 
List<string> stringList = ConvertList<string>(myList); 
+0

wie kann ich verstehen, dass ich ConvertList aufrufen sollte? Ich kenne nur Typ, ich kann nicht schreiben ConvertList

+0

Oh, sorry, ich bearbeite meine Antwort. –

0
public static List<T> ConvertType<T>(List<object> list) { 
    var list2 = new List<T>(); 
    for(int i=0;i<list.Count;i++) list2.Add((T)list[i]); 
    return list2; 
} 
+0

Wie kann ich verstehen, dass ich ConvertList aufrufen sollte? Ich kenne nur Typ, ich kann nicht schreiben ConvertList

+0

Ich sehe, dann müssen Sie Reflexion verwenden, um den generischen Typ zur Laufzeit zu machen, siehe Guillaume's Antwort (die ich nicht wiederholen werde). – kevin

1

Nicht sicher, ob dies überhaupt hilft, aber können Sie mit Linq Cast?

List<object> theList = new List<object>(){ 1, 2, 3}; 
List<int> listAsInt = theList.Cast<int>(); 
1
public static object ConvertList<T>(List<object> value) where T : class 
    { 
     var newlist = value.Cast<T>().ToList(); 
     return newlist; 
    } 

oder

public static List<T> ConvertList<T>(List<object> value) where T : class 
    { 
     List<T> newlist = value.Cast<T>().ToList(); 
     return newlist; 
    } 
8

Der Typ nur zur Laufzeit bekannt ist, so dass ich denke, generische Methode ist nicht die Art und Weise

public static object ConvertList(List<object> value, Type type) 
{ 
    IList list = (IList)Activator.CreateInstance(type); 
    foreach (var item in value) 
    { 
     list.Add(item); 
    } 
    return list; 
} 
+0

Ja, es ist eine schöne Lösung. Found thread hier -http: //stackoverflow.com/questions/2474119/dynamic-listt-type –

+0

Ich bin mir nicht sicher, ob das für die Typen funktioniert, die das OP erwähnt hat (zumindest Bool und Int), weil ein Liste der Objekte an erster Stelle die Werttypen wurden eingerahmt und können somit nicht zur Liste hinzugefügt werden. Edit: Eigentlich ist das nicht das Problem. Sie müssen 'Type [] typeArgs = {type};' in Ihrer Methode zu 'Type [] typeArgs = {type.GenericTypeArguments.First()};'; – Richiban

+0

@Richiban Sie haben Recht, ich habe fälschlicherweise erwartet, dass "Typ" der Typ des Elements ist. Behoben – Guillaume

0
/// <summary> 
    /// Converts list of items into typed list of item of new type 
    /// </summary> 
    /// <example><code> 
    /// Consider source to be List<object>, newItemType is typeof(string), so resulting list wil have type List<string> 
    /// </code></example> 
    /// <param name="newItemType">New item type</param> 
    /// <param name="source">List of objects</param> 
    /// <returns>Typed List object</returns> 
    public static IList ConvertList(Type newItemType, IList source) 
    { 
     var listType = typeof(List<>); 
     Type[] typeArgs = { newItemType }; 
     var genericListType = listType.MakeGenericType(typeArgs); 
     var typedList = (IList)Activator.CreateInstance(genericListType); 
     foreach (var item in source) 
     { 
      typedList.Add(item); 
     } 
     return typedList; 
    } 
Verwandte Themen