2011-11-01 12 views
9

Tengo un cuadro combinado donde se llena usando una colección de Anónimo Tipo:C# Anónimo Acceso Tipo de otro método

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

Luego, en el método SelectedIndexChanged del ComboBox, quiero recuperar el ID del seleccionado elemento, pero no puedo acceder a la propiedad "Id", en myComboBox.SelectedItem es el objeto seleccionado.

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

      ¿¿¿ ??? 
    } 
} 

¿Alguna idea?

+0

si solo necesita el ID puede usar myCombobox.SelectedValue? – saus

+2

La palabra clave * dynamic * te va a meter en problemas. Los miembros de tipo anónimo tienen acceso * interno *. O en otras palabras, no puede acceder a ellos cuando su código de UI se encuentra en un ensamblaje por separado. Lo cual es muy común, separar la UI del modelo de datos es una actividad que vale la pena. Simplemente no use un tipo anónimo aquí. –

+0

Usar anon y/o tipos dinámicos no es la respuesta aquí. ¿Qué pasa con tu propio tipo de peso ligero? (O, para este ejemplo en particular, ['KeyValuePair '] (http://msdn.microsoft.com/en-us/library/5tbh8a42.aspx)?) – LukeH

Respuesta

4

Puede usar la reflexión también.

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

El truco del encasillamiento es mucho más rápido que la reflexión, aunque no puedo decir cuál de ellos es más probable que continúe funcionando en versiones futuras de C#/CLR. –

9

Puesto que se utiliza como identificación ValueMember el Ello podría almacenarse como myComboBox.SelectedItem.Value

0

Puede utilizar dynamic palabra clave en lugar de var.

1

si está trabajando con C# 4.0, luego use la palabra clave dinámica, de lo contrario, defina una clase que contenga el id y el nombre en lugar de usar el tipo anónimo, o use el reflejo.

1

¿Necesita la solución más simple? Crea una clase llamada SimpleEntity con tres campos: Id, Descripción y Etiqueta. Esta clase debe tener un constructor que acepte un Objeto y, mediante la reflexión, obtendrá Id y Name y establecerá los dos campos. Y también establece la propiedad Tag con el objeto. De esta forma, solo necesitas completar el combo con esta nueva clase y luego recuperar el objeto original. Espero que ayude.

+0

Puede evitar la reflexión si el constructor acepta tres parámetros (int, cadena, objeto) –

0

Creo que sería mejor usar algo así como un Tuple<int, string> aquí, no un tipo anónimo, pero es posible para hacer lo que quieras. Dos tipos anónimos en el mismo ensamblaje que tienen los mismos nombres de campo y tipos de campo en el mismo orden se "doblan" internamente en un solo tipo. Puede usar esto para pasar instancias de tipo anónimo y, mediante la inferencia de tipo genérico, encasillarlos en una fecha posterior.

Tenga en cuenta que esto se basa en un mecanismo interno en el compilador de C#, por lo que no hay garantía de que continuará funcionando; sin embargo, funciona en todas las versiones actuales de C# que tienen tipos anónimos.

Actualización: Esto se llama en realidad explícitamente en la especificación de C#, por lo que este debe estar completamente seguro hacerlo:

dentro del mismo programa, dos inicializadores de objetos anónimos que especifican una serie de propiedades de la mismos nombres y tipos en el mismo orden producirá instancias del mismo tipo anónimo

Tenga en cuenta también que esto sólo funciona dentro de un único conjunto (no deje que la referencia de la especificación de un "programa" se confunda) . Para consumir tipos anónimos de otro ensamblado se requiere reflexión (y, IMO, generalmente es una muy mala idea.) Sin embargo, para escenarios de enlace de datos como el suyo, funciona bien.

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