2009-05-17 4 views
20

Ho un datagrid popolato da una query Linq. Quando la riga focalizzata nel datagrid cambia, ho bisogno di impostare una variabile uguale a una delle proprietà in quell'oggetto.Come posso ottenere un valore di una proprietà da un tipo anonimo?

ho provato ...

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

... ma il compilatore non si preoccupa per questo a tutti ("dichiarazione incorporato non può essere una dichiarazione o una dichiarazione etichettati").

Sembra che la proprietà dovrebbe essere di facile accesso. Ispezionare l'oggetto durante il runtime mostra tutte le proprietà che mi aspetto, ma non so come accedervi.

Come posso accedere alla proprietà dell'oggetto anonimo?

Edit chiarimenti:

mi capita di usare il controllo DevExpress XtraGrid. Ho caricato questo controllo con una query Linq composta da diversi oggetti diversi, rendendo quindi i dati non proprio conformi a qualsiasi classe che ho già (cioè, non posso trasmettere questo a qualcosa).

Sto usando .NET 3.5.

Quando osservo i risultati del metodo view.GetRow (rowHandle) ottengo un tipo anonimo che assomiglia a questo:

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

Il mio obiettivo è quello di ottenere il ClientId da questo tipo anonimi, in modo che io possa fare altre cose (come caricare un modulo con quel record del client in esso).

Ho provato un paio di suggerimenti nelle prime risposte ma non sono riuscito ad arrivare a un punto in cui avrei potuto ottenere questo ClientId.

+0

Qual è il tipo esatto dell'identificatore "vista"? – AnthonyWJones

+0

"Visualizza" è un controllo GridView di DevExpress. –

risposta

43

Hai mai provato a utilizzare il riflesso? Ecco un frammento di codice di esempio:

// 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... 
+0

Grazie abdoul, il tuo codice è abbastanza facile da capire. Recentemente ho avuto un problema nell'ottenere il tipo anonimo e qui: http: //stackoverflow.com/questions/3534969/only-parameterless-constructors-and-initializers-are-supported-in-linq-to-entitie Ho lasciato la domanda. Dopo un po 'di ricerche e di lavoro durante il fine settimana sono arrivato a questa pagina e ha davvero reso la mia giornata. – Developer

+0

Questo è esattamente il motivo per cui amo SO – Bergkamp

+0

Davvero, risposta troppo impressionante! Questo è quello che stavo cercando da 2 settimane! Grazie mille! – KomalJariwala

17

Uno dei problemi con i tipi anonimi è che è difficile usarli tra le funzioni. Non c'è modo di "nominare" un tipo anonimo e quindi è molto difficile fare il cast tra di loro. Ciò impedisce loro di essere utilizzati come espressione di tipo per tutto ciò che appare nei metadati e che è definito dall'utente.

Non riesco a dire esattamente quale API si sta utilizzando sopra. Tuttavia non è possibile che l'API restituisca un tipo anonimo fortemente tipizzato, quindi la mia ipotesi in quell'oggetto selezionato viene digitata come oggetto. C# 3.0 e seguenti non supportano l'accesso dinamico, quindi non sarà possibile accedere all'ID della proprietà anche se è disponibile in fase di esecuzione.

Sarà necessario uno dei seguenti per aggirare questo

  • Usa riflessione per afferrare la proprietà
  • creare un tipo completo e l'uso che per popolare il datagrid
  • Utilizzare uno dei tanti hacky tipo anonimo getta

EDIT

Ecco un esempio su come fare un tipo anonimo mod gettato

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

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

Il motivo è hacky è che è molto facile da rompere questo. Ad esempio nel metodo in cui il tipo anonimo è stato originariamente creato. Se aggiungo un'altra proprietà al tipo lì il codice sopra verrà compilato ma fallirà in fase di runtime.

+0

"casini di tipo anonimo hacky" quali sono quelli? – AnthonyWJones

+0

@AnthonyWJones, ho aggiunto un esempio di cast di tipo anonimo hacky – JaredPar

+0

Grazie per questa risposta. Una soluzione molto bella ed elegante. Ha solo un inconveniente: non funziona se l'oggetto anonimo proviene da un altro assembly. Questo è uno dei motivi per cui non si dovrebbe mai mai restituire un oggetto anonimo da un metodo, ma non tutti lo sanno e quindi devo occuparmi di una libreria che sfortunatamente fa esattamente questo. –

0

Questo potrebbe essere sbagliato (potresti non avere abbastanza codice lì) ma non hai bisogno di indicizzare nella riga in modo da scegliere quale colonna vuoi? O se "Id" è la colonna che si desidera, si dovrebbe fare qualcosa di simile:

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

Questo è come mi piacerebbe afferrare il contenuto di una colonna in un DataGrid. Ora se la colonna stessa è di tipo anonimo, allora non lo so, ma se stai ottenendo solo una colonna con un tipo primitivo, allora dovrebbe funzionare.

1

Come ha correttamente intuito JaredPar, il tipo restituito GetRow() è object. Quando si lavora con la griglia DevExpress, è possibile estrarre il valore desiderato in questo modo:

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

Questo approccio ha aspetti negativi simili come il "tipo hacky anonimo calchi" descritta prima: Avete bisogno di una stringa magica per identificare la colonna più un digitare cast da oggetto a int.

2

Quando stavo lavorando con il passaggio di tipi anonimi e cercando di riformularli, alla fine ho trovato più facile scrivere un wrapper che gestiva il lavoro con l'oggetto. Ecco un link a un post del blog su di esso.

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

In ultima analisi, il codice sarebbe simile a questa.

//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"); 
0

Spero che questo aiuti, sto passando in un elenco di interfaccia, che ho bisogno di ottenere una lista distinta da. Prima di tutto ottengo una lista di tipi anonimi, e poi la passo per trasferirla nella mia lista di oggetti.

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; 
      } 
17

Una soluzione generica per ottenere il valore di un elemento di dati per una chiave determinata

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; 
} 

Esempio:

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

Ho trovato questa soluzione la migliore per dichiarare i tipi anonimi. Grazie. – DoomerDGR8

0

È possibile scorrere le proprietà di un tipo anonimo come questo :

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

DevExpre xtraGridView di ss ha un metodo come questo GetRowCellDisplayText (int rowHandle, colonna GridColumn). Con questo metodo, il seguente codice restituisce l'id dal tipo anonimo.

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

Anche se questo non fornisce una risposta alla domanda: "Come posso ottenere l'accesso alla proprietà dell'oggetto anonimo?", Si tenta ancora di risolvere la causa principale del problema.

ho provato questo con Devexpress versione 11.1 e posso vedere che la questione è stato chiesto quasi 2,5 anni fa. Forse l'autore della domanda potrebbe avere una soluzione alternativa o trovato la soluzione da solo. Tuttavia, sto ancora rispondendo in modo che possa aiutare qualcuno.

11

è possibile utilizzare il tipo dinamico per accedere alle proprietà di tipi anonimi in fase di esecuzione senza l'utilizzo di riflessione.

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

saperne di più sul tipo dinamico qui: http://msdn.microsoft.com/en-us/library/dd264736.aspx

+0

Così semplice ed elegante mi vergogno di non pensarci :) – percebus

0

Se si sa cosa si sta facendo e non hanno paura di avere errori di runtime quando le modifiche di codice, si potrebbe lanciare i vostri dati della riga come dynamic:

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

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

Nessuna verifica del tempo di compilazione. Ma dovrebbe funzionare bene.

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

Questo è il modo più semplice per ottenere il valore degli attributi di una lista (DataGridView) –