web-dev-qa-db-fra.com

Objet converti en liste générique

J'ai 3 liste de type générict.

List<Contact> = new List<Contact>();
List<Address> = new List<Address>();
List<Document> = new List<Document>();

Et enregistrez-le sur une variable avec un objet type. Maintenant, je fais Cast Retour à la liste pour exécuter une foreach, certains comme ceci:

List<Contact> = (List<Contact>)obj;

Mais les contenus obj changent à chaque fois, et j'en ai comme ça:

List<???> = (List<???>)obj;

J'ai une autre variable de maintien actuelle obj Type:

Type t = typeof(obj);

Puis-je faire quelque chose comme ça ??:

List<t> = (List<t>)obj;

Obs: Je n'ai pas le type actuel dans la liste mais j'ai besoin de lancer, et je n'ai pas maintenant un autre formulaire à la place: 

List<Contact> = new List<Contact>();
12
JoeLoco

Quel problème collant. Essaye ça:

List<Contact> c = null;
List<Address> a = null;
List<Document> d = null;

object o = GetObject();

c = o as List<Contact>;
a = o as List<Address>;
d = o as List<Document>;

Entre c, a et d, il y a 2 Nuls et 1 Non-Nul, ou 3 Nuls.


Prendre 2:

object o = GetObject();
IEnumerable e = o as IEnumerable;
IEnumerable<Contact> c = e.OfType<Contact>();
IEnumerable<Address> a = e.OfType<Address>();
IEnumerable<Document> d = e.OfType<Document>();
28
Amy B

Cela m'a valu beaucoup d'essais et d'erreurs sur la SL 5, mais cela devrait également fonctionner sur un C # ordinaire. Vous devez également ajouter LINQ à votre liste d’utilisation pour que la dernière moitié fonctionne.

    List<object> myAnythingList = (value as IEnumerable<object>).Cast<object>().ToList()

Prendre plaisir!

23
Andrew Marais

J'ai eu le même problème et l'ai résolu en regardant l'objectif des objets en fonte. Avez-vous vraiment besoin de le convertir en types génériques spécifiques (fermés)? Dans mon cas, le type générique (ouvert) avait une interface vers laquelle je l'avais utilisé. 

var list = obj as IUsefulInterface;

list.MethodThatIAmInterestedIn();
2
Vincent65535

Une solution générale comme celle-ci (instancier un type avec un paramètre générique basé sur un objet System.Type) n'est pas possible. Si vous ne vous occupez que de ces trois types, vous avez de la chance car c'est assez simple:

Type t = typeof(obj);

if (t == typeof(List<Contact>)) {
    var contactList = (List<Contact>)obj;
    // do stuff with contactList

} else if (t == typeof(List<Address>)) {
    var addressList = (List<Address>)obj;
    // do stuff with addressList

} else if (t == typeof(List<Document>)) {
    var documentList = (List<Document>)obj;
    // do stuff with documentList
}
1
Dan Tao

J'ai rencontré ce problème lors de l'écriture d'un attribut de validation dans lequel j'ai reçu un objet de la variable ValidationContext et je savais qu'il devait s'agir d'une liste, mais pas de ce que c'était. Il a lancé une exception lorsque j'ai essayé de le convertir en IEnumerable<object>, mais il pourrait être converti en IEnumerable, ce qui a ensuite permis à la fonction .Cast<object>() via linq.

En fin de compte, ce qui a fonctionné a été:

var enumerable = listObject as IEnumerable;
var list = enumerable.Cast<object>().ToList();
0
ste-fu

J'ai rencontré le même problème - j'ai une collection dont le type de données n'est connu qu'au moment de l'exécution et je ne peux le convertir en rien. Aucune des solutions ci-dessus n'a fonctionné. Enfin, je l'ai résolu en sérialisant au format JSON et en le désérialisant. Bien sûr, ce n'est pas idéal, mais peut aider quelqu'un.

string jsonString = JsonConvert.SerializeObject(myObject);
jsonString = "{ values:" + jsonString + "}";

JObject j = JObject.Parse(jsonString);

//now we can iterate over the list
foreach (var x in j["values"])
{
    string name = x.ToString();
    ...
}
0
Vadim

Non, vous ne pouvez pas lancer sans tourner dans les angles (c'est-à-dire: réflexion), les paramètres de type générique doivent être connus au moment de la compilation. Vous pouvez bien sûr faire quelque chose comme ça:

content.Where(o => o is type).ToList().Foreach(stuff);

0
Femaref