2011-11-01 13 views
9

ho una casella combinata in cui viene riempito con una collezione di Anonymous Tipo:Tipo C# anonimo accesso da altro metodo

var results = (from row in data.Tables[0].AsEnumerable() 
       select new { 
        Id = row.Field<int>("id"), 
        Name = row.Field<string>("Name 
       }).Distinct(); 

myComboBox.ValueMember = "Id"; 
myComboBox.DisplayMember = "Name"; 

foreach (var n in results) 
{ 
    myComboBox.Items.Add(n); 
} 

Poi, nel metodo SelectedIndexChanged del comboBox, voglio recuperare l'ID del selezionato elemento, ma non posso accedere alla proprietà "Id", in myComboBox.SelectedItem è l'oggetto selezionato.

private void myComboBox_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    if (myComboBox.SelectedItem != null) 
    { 
     var x = myComboBox.SelectedItem; 

      ¿¿¿ ??? 
    } 
} 

Qualche idea?

+0

se hai solo bisogno dell'id puoi usare myCombobox.SelectedValue? – saus

+2

La parola chiave * dynamic * ti metterà nei guai. I membri di un tipo anonimo hanno accessibilità * interna *. In altre parole, non puoi accedervi quando il tuo codice UI si trova in un assembly separato. Il che è molto comune, separare l'interfaccia utente dal modello di dati è una ricerca degna. Semplicemente non usare un tipo anonimo qui. –

+0

L'uso di anon e/o tipi dinamici non è la risposta qui. Cosa c'è che non va nel tuo tipo leggero? (Oppure, per questo particolare esempio, ['KeyValuePair '] (http://msdn.microsoft.com/en-us/library/5tbh8a42.aspx)?) – LukeH

risposta

4

È possibile utilizzare anche la riflessione.

private void myComboBox_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    if (myComboBox.SelectedItem != null) 
    { 
     var x = myComboBox.SelectedItem; 
     System.Type type = x.GetType(); 
     int id = (int)type.GetProperty("Id").GetValue(obj, null); 
    } 
} 
+1

Il trucco typecasting è molto più veloce della riflessione, anche se non posso dire quale di essi abbia più probabilità di continuare a funzionare nelle versioni future di C#/CLR. –

9

Dal momento che si utilizza come Id ValueMember l'Es sarebbe memorizzato come myComboBox.SelectedItem.Value

0

È possibile utilizzare dynamic parola chiave al posto di var.

1

se si sta lavorando con C# 4.0, quindi utilizzare la parola chiave dinamica, altrimenti, definire una classe che contiene id e nome invece di utilizzare il tipo anonimo, o utilizzare reflection.

1

Avete bisogno della soluzione più semplice? Crea una classe chiamata SimpleEntity con tre campi: Id, Descrizione e Tag. Questa classe dovrebbe avere un costruttore che accetta un oggetto e, usando la reflection, ottieni Id e Name e imposta i due campi. E si imposta anche la proprietà Tag con l'oggetto. In questo modo, è sufficiente popolare la combo utilizzando questa nuova classe e quindi si ottiene di nuovo l'oggetto originale. Spero che aiuti.

+0

È possibile evitare il riflesso se il costruttore accetta tre parametri (int, stringa, oggetto) –

0

Penso che sarebbe meglio usare qualcosa come un Tuple<int, string> qui, non un tipo anonimo, ma è possibile fare quello che vuoi. Due tipi anonimi nello stesso assembly che hanno gli stessi nomi di campo e tipi di campo nello stesso ordine sono internamente "piegati" in un singolo tipo. È possibile utilizzarlo per passare istanze di tipo anonimo e, utilizzando l'inferenza di tipo generico, inserirli in un secondo momento.

Si noti che questo si basa su un meccanismo interno nel compilatore C#, quindi non c'è alcuna garanzia che continuerà a funzionare; funziona, tuttavia, in ogni versione corrente di C# che ha tipi anonimi.

Update: Questo è in realtà chiamato esplicitamente in C# spec, quindi questo dovrebbe essere completamente sicuri da fare:

all'interno dello stesso programma, due inizializzatori oggetto anonimo che specificano una sequenza di proprietà del stessi nomi e tipi nello stesso ordine produrrà istanze dello stesso tipo anonimo

si noti inoltre che questo funziona solo all'interno di un singolo gruppo di (non lasciare che il riferimento della specifica ad un "programma" confondere voi) . Il consumo di tipi anonimi da un altro assembly richiede una riflessione (e, IMO, è generalmente una pessima idea.) Tuttavia, per gli scenari di associazione dei dati come il tuo, funziona correttamente.

public object foo; 

public void Create() 
{ 
    this.foo = new { Id = 1, Name = "Melvin" }; 
} 

public void Consume() 
{ 
    var x = new { Id = 0, Name = String.Empty }; 
    var y = this.Cast(this.foo, x); 
} 

public T Cast<T> (object o, T template) 
{ 
    return (T)o; 
} 
Problemi correlati