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

j'ai un datagrid peuplé d'une requête Linq. Lorsque la ligne focalisée dans le datagrid change, j'ai besoin de définir une variable égale à l'une des propriétés de cet objet.

j'ai essayé...

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

... mais le compilateur n'a pas de soins pour ce ("Embedded déclaration ne peut pas être une déclaration ou une déclaration intitulée").

il semble que la propriété devrait être facile d'accès. Inspecter l'objet pendant l'exécution montre toutes les propriétés que j'attends, je juste ne sais pas comment y accéder.

Comment puis-je accéder à la propriété de l'objet anonyme?

Modifier pour les Précisions:

<!-Il se trouve que J'utilise DevExpress XtraGrid control. J'ai chargé ce contrôle avec une requête Linq qui était composée de plusieurs objets différents, ce qui fait que les données ne sont pas vraiment conformes à une classe que j'ai déjà (c'est-à-dire que je ne peux pas lancer cela à quoi que ce soit).

je suis en utilisant .NET 3.5.

quand je vois les résultats de la vue.Méthode GetRow(rowHandle) j'obtiens un type anonyme qui ressemble à ceci:

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

mon objectif est d'obtenir le ClientId de ce type anonyme afin que je puisse faire d'autres choses (comme charger un formulaire avec ce dossier client).

j'ai essayé quelques suggestions dans les premières réponses mais j'ai été incapable d'arriver à un point où je pourrais obtenir ce ClientId.

20
demandé sur Sailing Judo 2009-05-17 18:35:33

12 réponses

Avez-vous déjà essayé d'utiliser la réflexion? Voici un exemple de code snippet:

// use reflection to retrieve 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);
string clientname = (string)type.GetProperty("ClientName").GetValue(obj, null);

// use the retrieved values for whatever you want...
46
répondu Bigabdoul 2010-07-28 23:33:38

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<T>( object dataitem, string 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<bool>(dataitem, "IsMember");
18
répondu wcm 2011-09-28 07:56:19

Un des problèmes avec les types anonymes, c'est qu'il est difficile de les utiliser entre les fonctions. Il n'y a aucun moyen de "nommer" un type anonyme et il est donc très difficile de les séparer. Cela les empêche d'être utilisées comme expression de type pour tout ce qui apparaît dans les métadonnées et est 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 retourner un type anonyme fortement tapé, donc à mon avis selectedObject est tapé à object. C# 3.0 et ci-dessous ne supporte pas l'accès dynamique donc vous ne pourrez pas accéder à l'Id de la propriété même s'il est disponible à l'exécution.

Vous aurez besoin d'une des méthodes suivantes pour contourner ce problème

  • Utiliser la réflexion pour saisir la propriété
  • Créer un type complet et l'utiliser pour remplir la grille de données
  • utilisez l'un des nombreux moulages de type hacky anonymous

EDIT

voici un exemple sur la façon de faire un piratage anonyme type cast

public T AnonymousTypeCast<T>(object anonymous, T typeExpression) { 
  return (T)anonymous;
}

...
object obj = GetSomeAnonymousType();
var at = AnonymousTypeCast(obj, new { Name = String.Empty, Id = 0 });

la raison pour laquelle c'est hacky est qu'il est très facile de briser ceci. 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 compilera mais échouera à l'exécution.

17
répondu JaredPar 2009-05-17 14:58:22

Vous pouvez utiliser le type dynamique pour accéder aux propriétés des types anonymes à l'exécution sans utiliser la réflexion.

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

Lire plus sur le type dynamique ici:http://msdn.microsoft.com/en-us/library/dd264736.aspx

14
répondu Per 2012-03-30 07:04:33

quand je travaillais avec des types anonymes et que j'essayais de les refondre, j'ai finalement trouvé plus facile d'écrire un wrapper qui fonctionnait avec l'objet. Voici un lien vers un billet 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((string name, int age) => {  
  Console.Write("{0} :: {1}", name, age);  
}); 

//or just single values
int value = type.Get<int>("age");   
3
répondu Hugoware 2009-05-29 16:25:40

Comme JaredPar deviné correctement, le type de retour de GetRow()object. En travaillant avec la grille DevExpress, vous pouvez extraire la valeur désirée comme ceci:

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

cette approche a des inconvénients similaires comme les "hacky anonymous type casts" décrits ci-dessus: vous avez besoin d'une chaîne magique pour identifier la colonne plus un type cast de l'objet à l'int.

1
répondu Sven Künzler 2009-05-17 16:49:25

Xtragridview de DevExpress a une méthode comme celle-ci GetRowCellDisplayText(int rowHandle, gridcolumn column column). Avec cette méthode, le code suivant renvoie l'id du type anonyme.

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

bien que cela ne fournisse pas une réponse à la question "Comment puis-je accéder à la propriété de l'objet anonyme?", il tente toujours de résoudre la cause racine du problème.

j'ai essayé avec la version 11.1 de devXpress et je peux voir que la question a d'abord été posée il y a presque 2,5 ans. Il est possible que l'auteur de la question ait trouvé lui-même la solution. Pourtant, je continue de répondre pour que cela puisse aider quelqu'un.

1
répondu Narayanan 2011-12-28 05:29:09

cela peut être erroné (vous n'avez peut-être pas assez de code) mais vous n'avez pas besoin d'indexer dans la rangée donc vous choisissez quelle colonne vous voulez? Ou si "Id" est la colonne que vous voulez, vous devriez être en train de faire quelque chose comme ceci:

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

Voici comment j'attraperais le contenu d'une colonne dans un datagrid. 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.

0
répondu Kevin Anderson 2009-05-17 15:03:17

j'Espère que cette aide, suis de passage dans une liste d'interface, j'ai besoin d'obtenir une liste distincte. D'abord, J'ai une liste de type anonyme, et ensuite je la passe pour la transférer sur ma liste d'objets.

private List<StockSymbolResult> GetDistinctSymbolList( List<ICommonFields> l )
            {
                var DistinctList = (
                        from a
                        in l
                        orderby a.Symbol
                        select new
                        {
                            a.Symbol,
                            a.StockID
                        } ).Distinct();

                StockSymbolResult ssr;
                List<StockSymbolResult> rl = new List<StockSymbolResult>();
                foreach ( var i in DistinctList )
                {
                                // Symbol is a string and StockID is an int.
                    ssr = new StockSymbolResult( i.Symbol, i.StockID );
                    rl.Add( ssr );
                }

                return rl;
            }
0
répondu MikeMalter 2010-10-11 23:10:43

Vous pouvez boucler 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);
    ...
}
0
répondu Lasse Skindstad Ebert 2011-03-24 14:55:42

si vous savez ce que vous faites et que vous n'avez pas peur d'avoir des erreurs d'exécution lorsque votre code change, vous pouvez lancer vos données de ligne comme dynamic:

var data = view.GetRow(rowHandle) as dynamic;  

int clientId      = data.ClientID;
string clientName = data.ClientName;
int jobs          = data.Jobs

pas de vérification de la compilation. Mais il devrait fonctionner très bien.

0
répondu Renaud Bompuis 2013-07-23 08:36:34
var result = ((dynamic)DataGridView.Rows[rowNum].DataBoundItem).value;
0
répondu Rei Salazar 2015-12-30 21:45:50