web-dev-qa-db-fra.com

Convertir la liste de type anonyme en liste d'objets dynamiques

Pourquoi ne puis-je pas lancer un List<AnonymousObject> à un List<dynamic>? J'ai ce code suivant:

var datasource = someList.Select(o => new { x = o.A, y = o.B });
dgvSomeGridView.DataSource = datasource.ToList();
dgvSomeGridView.DataBind();

J'accède ensuite au GridView.DataSource avec le code suivant:

var ds = ((List<dynamic>)dgvSomeGridView.DataSource);
....

Mais il jette une erreur sur la ligne où je l'ai jeté sur List<dynamic>, ça dit:

Impossible de caster un objet de type System.Collections.Generic.List'1[<>f__AnonymousType0'8[System.Int32,System.String]] pour taper System.Collections.Generic.List'1[System.Object].

Pourquoi ne puis-je pas caster une liste de types anonymes dans un dynamic, ou comme l'erreur l'indique dans un type object? Comment puis-je résoudre ça?

Mon code est en C #, framework 4.0, construit en VS2010 Pro, la plateforme est ASP.NET.

Veuillez aider, merci d'avance.

18

Puisque List<T> est en variante, pas en co-variante, vous devez donc transtyper en IEnumerable<dynamic> qui prend en charge la co-variante:

var ds = ((IEnumerable<dynamic>)dgvSomeGridView.DataSource).ToList();

Pour en savoir plus informations sur la covariante

42
cuongle

Premièrement, Casting avec générique ne fonctionne pas de cette façon. Cette distribution n'est pas valide:

List<string> source = GetStrings();
List<object> source2 = (List<object>) source;

La raison en est que List n'est pas co-variant. Si c'était le cas, vous pourriez source2.Add(source2); et soudainement source1 se contient alors qu'il ne devrait avoir que des chaînes.

Deuxièmement, types anonymes ne sont que des classes déclarées par le compilateur avec des propriétés en lecture seule et une sémantique d'égalité des valeurs. Si vous avez créé une classe avec des propriétés en lecture seule et une sémantique d'égalité des valeurs, votre classe serait identique à un type anonyme, sauf que votre type aurait un nom déterminé par le développeur, tandis que le type anonyme a un nom déterminé par le compilateur. Les types anon ne sont pas spéciaux.

Troisièmement, les variables dynamiques sont un moyen de contourner la vérification du type de compilateur. Ils ne contournent pas la vérification du type d'exécution. Vous pouvez utiliser la syntaxe de casting c # pour convertir explicitement le type en dynamique ... note: ce n'est pas un cast! Vous ne pouvez pas effectuer de transtypage d'exécution vers un type qui n'existe pas au moment de l'exécution.

Toutefois, les opérations qui contiennent des expressions de type dynamique ne sont pas résolues ou vérifiées par le compilateur. Le compilateur regroupe des informations sur l'opération, et ces informations sont ensuite utilisées pour évaluer l'opération au moment de l'exécution. Dans le cadre du processus, les variables de type dynamique sont compilées en variables de type objet. Par conséquent, le type dynamique n'existe qu'au moment de la compilation, pas au moment de l'exécution.

static void convertToDynamic()
{
    dynamic d;
    int i = 20;
    d = (dynamic)i;
    Console.WriteLine(d);

    string s = "Example string.";
    d = (dynamic)s;
    Console.WriteLine(d);

    DateTime dt = DateTime.Today;
    d = (dynamic)dt;
    Console.WriteLine(d);

}
// Results: 
// 20 
// Example string. 
// 2/17/2009 9:12:00 AM

Enfin, si vous voulez toujours un List<dynamic>, Faites ceci:

var anonList = GetAnonList();
List<dynamic> dynamicList = anonList.Select(x => (dynamic)x).ToList();

Mais vous pouvez tout aussi facilement le faire:

var anonList = GetAnonList();
List<object> objectList = anonList.Cast<object>().ToList();
8
Amy B