Comment puis-je obtenir la valeur d’une propriété d’un type anonyme?

J’ai une grid de données remplie par une requête Linq. Lorsque la ligne focalisée dans la grid de données change, je dois définir une variable égale à l’une des propriétés de cet object.

J’ai essayé…

var selectedObject = view.GetRow(rowHandle); _selectedId = selectedObject.Id; 

… mais le compilateur ne s’en soucie pas du tout (“L’instruction incorporée ne peut pas être une déclaration ou une instruction étiquetée”).

Il semble que la propriété devrait être facile d’access. L’inspection de l’object au cours de l’exécution montre toutes les propriétés attendues, mais je ne sais pas comment y accéder.

Comment puis-je accéder à la propriété de l’object anonyme?

Modifier pour clarifications:

Il se trouve que j’utilise le contrôle DevExpress XtraGrid. J’ai chargé ce contrôle avec une requête Linq composée de plusieurs objects différents, rendant ainsi les données non conformes à une classe que j’ai déjà (c’est-à-dire que je ne peux pas le convertir en rien).

J’utilise .NET 3.5.

Lorsque je visualise les résultats de la méthode view.GetRow (rowHandle), je reçois un type anonyme qui ressemble à ceci:

 { ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 } 

Mon objective est d’obtenir le ClientId de ce type anonyme afin que je puisse faire d’autres choses (comme charger un formulaire contenant cet enregistrement client).

J’ai essayé quelques-unes des suggestions dans les premières réponses mais je n’ai pas réussi à obtenir un point où je pourrais obtenir ce ClientId.

Avez-vous déjà essayé d’utiliser la reflection? Voici un exemple d’extrait de code:

 // use reflection to resortingeve the values of the following anonymous type var obj = new { ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 }; System.Type type = obj.GetType(); int clientid = (int)type.GetProperty("ClientId").GetValue(obj, null); ssortingng clientname = (ssortingng)type.GetProperty("ClientName").GetValue(obj, null); // use the resortingeved values for whatever you want... 

Une solution générique pour obtenir la valeur d’un élément de données pour une clé donnée

 public static T GetValueFromAnonymousType( object dataitem, ssortingng itemkey ) { System.Type type = dataitem.GetType(); T itemvalue = (T)type.GetProperty(itemkey).GetValue(dataitem, null); return itemvalue; } 

Exemple:

 var dataitem = /* Some value here */; bool ismember = TypeUtils.GetValueFromAnonymousType(dataitem, "IsMember"); 

L’un des problèmes avec les types anonymes est qu’il est difficile de les utiliser entre les fonctions. Il n’existe aucun moyen de “nommer” un type anonyme et il est donc très difficile d’interagir entre eux. Cela empêche leur utilisation en tant qu’expression de type pour tout élément apparaissant dans les métadonnées et défini par l’utilisateur.

Je ne peux pas dire exactement quelle API vous utilisez ci-dessus. Cependant, il n’est pas possible pour l’API de renvoyer un type anonyme fortement typé, donc je suppose que selectedObject est typé en object. C # 3.0 et versions ultérieures ne prennent pas en charge l’access dynamic, vous ne pourrez donc pas accéder à la propriété Id même si elle est disponible au moment de l’exécution.

Vous aurez besoin de l’une des méthodes suivantes pour contourner ce problème.

  • Utilisez la reflection pour saisir la propriété
  • Créez un type complet et utilisez-le pour remplir la grid de données
  • Utilisez l’un des nombreux transtypages anonymes de hacky

MODIFIER

Voici un exemple sur la façon de faire un casting de type anonyme de hack

 public T AnonymousTypeCast(object anonymous, T typeExpression) { return (T)anonymous; } ... object obj = GetSomeAnonymousType(); var at = AnonymousTypeCast(obj, new { Name = Ssortingng.Empty, Id = 0 }); 

C’est parce qu’il est très facile de casser ça. Par exemple, dans la méthode où le type anonyme est créé à l’origine. Si j’ajoute une autre propriété au type, le code ci-dessus sera compilé mais échouera au moment de l’exécution.

Vous pouvez utiliser le type dynamic pour accéder aux propriétés des types anonymes au moment de l’exécution sans utiliser de reflection.

 var aType = new { id = 1, name = "Hello World!" }; //... //... dynamic x = aType; Console.WriteLine(x.name); // Produces: Hello World! 

En savoir plus sur le type dynamic ici: http://msdn.microsoft.com/en-us/library/dd264736.aspx

Lorsque je travaillais avec la transmission de types anonymes et que j’essayais de les reformuler, j’ai finalement trouvé qu’il était plus facile d’écrire un wrapper gérant le travail avec l’object. Voici un lien vers un article de blog à ce sujet.

http://somewebguy.wordpress.com/2009/05/29/anonymous-types-round-two/

En fin de compte, votre code ressemblerait à quelque chose comme ça.

 //create an anonymous type var something = new { name = "Mark", age = 50 }; AnonymousType type = new AnonymousType(something); //then access values by their property name and type type.With((ssortingng name, int age) => { Console.Write("{0} :: {1}", name, age); }); //or just single values int value = type.Get("age"); 

Comme JaredPar l’a bien deviné, le type de retour de GetRow() est object . Lorsque vous travaillez avec la grid DevExpress, vous pouvez extraire la valeur souhaitée comme ceci:

 int clientId = (int)gridView.GetRowCellValue(rowHandle, "ClientId"); 

Cette approche présente des inconvénients similaires à ceux décrits ci-dessus pour les “conversions de type anonyme anonymes”: vous avez besoin d’une chaîne magique pour identifier la colonne, ainsi que d’une conversion de type d’object à int.

La méthode xtraGridView de DevExpress a une méthode comme celle-ci GetRowCellDisplayText (int rowHandle, colonne GridColumn). Avec cette méthode, le code suivant retourne l’id du type anonyme.

 var _selectedId = view.GetRowCellDisplayText(rowHandle, "Id"); 

Bien que cela ne permette pas de répondre à la question “Comment puis-je accéder à la propriété de l’object anonyme?”, Il tente toujours de résoudre le problème à la source.

J’ai essayé cela avec la version 11.1 de devXpress et je constate que la question a été posée pour la première fois il y a près de deux ans et demi. L’auteur de la question aurait peut-être pu contourner le problème ou trouver la solution lui-même. Pourtant, je réponds toujours pour que cela puisse aider quelqu’un.

Cela peut être faux (vous n’avez peut-être pas assez de code ici) mais n’avez-vous pas besoin d’indexer dans la ligne pour choisir la colonne de votre choix? Ou si “Id” est la colonne que vous voulez, vous devriez faire quelque chose comme ça:

 var selectedObject = view.GetRow(rowHandle); _selectedId = selectedObject["Id"]; 

Voici comment je prendrais le contenu d’une colonne dans une grid de données. Maintenant, si la colonne elle-même est un type anonyme, alors je ne sais pas, mais si vous obtenez juste une colonne nommée avec un type primitif, alors cela devrait fonctionner.

En espérant que cela aide, je passe une liste d’interfaces dont je dois obtenir une liste distincte. J’obtiens d’abord une liste de types anonymes, puis je la guide pour la transférer dans ma liste d’objects.

 private List GetDistinctSymbolList( List l ) { var DistinctList = ( from a in l orderby a.Symbol select new { a.Symbol, a.StockID } ).Distinct(); StockSymbolResult ssr; List rl = new List(); foreach ( var i in DistinctList ) { // Symbol is a ssortingng and StockID is an int. ssr = new StockSymbolResult( i.Symbol, i.StockID ); rl.Add( ssr ); } return rl; } 

Vous pouvez parcourir les propriétés d’un type anonyme comme ceci:

 var obj = new {someValue = "hello", otherValue = "world"}; foreach (var propertyInfo in obj.GetType().GetProperties() { var name = propertyInfo.Name; var value = propertyInfo.GetValue(obj, index: null); ... } 

Si vous savez ce que vous faites et que vous n’avez pas peur des erreurs d’exécution lorsque votre code change, vous pouvez convertir les données de votre ligne en données dynamic :

 var data = view.GetRow(rowHandle) as dynamic; int clientId = data.ClientID; ssortingng clientName = data.ClientName; int jobs = data.Jobs 

Pas de vérification à la compilation. Mais cela devrait bien fonctionner.

 var result = ((dynamic)DataGridView.Rows[rowNum].DataBoundItem).value;