Cast vers le type anonyme

J’ai eu le problème suivant aujourd’hui, et je me demandais s’il y avait une solution à mon problème.

Mon idée était de créer des classes anonymes et de les utiliser comme source de données pour une WinForm BindingSource:

public void Init() { var option1 = new { Id = TemplateAction.Update, Option = "Update the Templates", Description = "Bla bla 1." }; var option2 = new { Id = TemplateAction.Download, Option = "Download the Templates", Description = "Bla bla 2." }; var list = new[] {option1, option2}.ToList(); bsOptions.DataSource = list; // my BindingSource // cboTemplates is a ComboBox cboTemplates.DataSource = bsOptions; cboTemplates.ValueMember = "Id"; cboTemplates.DisplayMember = "Option"; lblInfoTemplates.DataBindings.Add("Text", bsOptions, "Description"); } 

Cela fonctionne bien jusqu’à présent.

Le problème que j’ai eu est de sortir l’Id de la propriété “Current” du BindingSource, parce que je ne peux pas le renvoyer au Type anonyme:

 private void cmdOK_Click(object sender, EventArgs e) { var option = (???)bsOptions.Current; } 

Je suppose qu’il n’y a aucun moyen de trouver le type de “Current” et d’accéder à la propriété “Id”? Peut-être que quelqu’un a une bonne solution …

Je sais qu’il existe d’autres moyens (et aussi meilleurs) d’obtenir l’ID (reflection, lecture de la valeur du contrôle ComboBox, sans tpyes anonymes, …) Je suis juste courageux s’il est possible d’extraire le Type de bsOptions. Courant de manière élégante.

Notez que, selon le commentaire, je voudrais simplement souligner que je recommande également d’utiliser un type réel lorsque vous devez le faire circuler dans le programme comme celui-ci. Les types anonymes ne devraient vraiment être utilisés que localement dans une seule méthode à la fois (à mon avis), mais de toute façon, voici le rest de ma réponse.


Vous pouvez le faire en utilisant une astuce, en incitant le compilateur à déduire le bon type pour vous:

 using System; namespace ConsoleApplication4 { class Program { static void Main(ssortingng[] args) { var a = new { Id = 1, Name = "Bob" }; TestMethod(a); Console.Out.WriteLine("Press enter to exit..."); Console.In.ReadLine(); } private static void TestMethod(Object x) { // This is a dummy value, just to get 'a' to be of the right type var a = new { Id = 0, Name = "" }; a = Cast(a, x); Console.Out.WriteLine(a.Id + ": " + a.Name); } private static T Cast(T typeHolder, Object x) { // typeHolder above is just for comstackr magic // to infer the type to cast x to return (T)x; } } } 

L’astuce est qu’à l’intérieur de l’assemblage, le même type anonyme (mêmes propriétés, même ordre) se résout dans le même type, ce qui rend le tour au-dessus du travail.

 private static T CastTo(this Object value, T targetType) { // targetType above is just for comstackr magic // to infer the type to cast x to return (T)x; } 

usage:

 var value = x.CastTo(a); 

Mais nous repoussons vraiment les limites ici. Utilisez un type réel, il aura l’air plus propre.

Au lieu de convertir en type personnalisé, essayez d’utiliser le type dynamic.

Votre gestionnaire d’événements ressemblerait à ceci:

 private void cmdOK_Click(object sender, EventArgs e) { dynamic option = bsOptions.Current; if (option.Id == 1) { doSomething(); } else { doSomethingElse(); } } 

Pour citer MSDN :

Un type anonyme ne peut être converti en aucune interface ou type sauf pour object.

En C # 3.0, ce n’est pas possible. Vous devrez attendre C # 4.0, qui permet d’accéder aux propriétés à l’exécution en utilisant des variables “dynamics”.

vous pouvez essayer ceci:

 private void cmdOK_Click(object sender, EventArgs e) { var option = Cast(bsOptions.Current, new { Id = 0, Option = "", Description = "" }); } 

voir: Impossible de renvoyer le type anonyme de la méthode? Vraiment?

 public class MyExtensMethods{ public static T GetPropertyValue(this Object obj, ssortingng property) { return (T)obj.GetType().GetProperty(property).GetValue(obj, null); } } class SomeClass { public int ID{get;set;} public int FullName{get;set;} } // casts obj to type SomeClass public SomeClass CastToSomeClass(object obj) { return new SomeClass() { ID = obj.GetPropertyValue("Id"), FullName = obj.GetPropertyValue("LastName") + ", " + obj.GetPropertyValue("FirstName") }; } 

…. pour lancer, vous ferez:

 var a = new { Id = 1, FirstName = "Bob", LastName="Nam" }; SomeClass myNewVar = CastToSomeClass(a); 

Vous pouvez également déclarer un tableau de types anonymes directement avec cette syntaxe:

 var data = new [] { new {Id = 0, Name = "Foo"}, new {Id = 42, Name = "Bar"}, };