2009-05-17 12 views
20

Tengo una cuadrícula de datos poblada por una consulta Linq. Cuando la fila enfocada en la cuadrícula de datos cambia, necesito establecer una variable igual a una de las propiedades en ese objeto.¿Cómo puedo obtener un valor de una propiedad de un tipo anónimo?

Probé ...

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

... pero el compilador no se preocupa por esto en absoluto ("Embedded declaración no puede ser una declaración o manifestación labled").

Parece que la propiedad debe ser de fácil acceso. Inspeccionar el objeto durante el tiempo de ejecución muestra todas las propiedades que espero, simplemente no sé cómo acceder a ellas.

¿Cómo puedo obtener acceso a la propiedad del objeto anónimo?

Editar para Aclaraciones:

que se esté utilizando el control DevExpress XtraGrid. Cargué este control con una consulta Linq que estaba compuesta de varios objetos diferentes, por lo tanto los datos no se ajustaban realmente a ninguna clase que ya tenga (es decir, no puedo convertir esto en nada).

Estoy usando .NET 3.5.

Cuando veo los resultados del método view.GetRow (rowHandle) me sale un tipo anónimo que tiene este aspecto:

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

Mi objetivo es conseguir que el ClientId de este tipo anónimo por lo que puedo hacer otras cosas (como cargar un formulario con ese registro de cliente en él).

Intenté algunas de las sugerencias en las primeras respuestas, pero no pude llegar a un punto donde pudiera obtener este ID de cliente.

+0

¿Cuál es el tipo exacto del identificador de "vista"? – AnthonyWJones

+0

"Ver" es un control GridView de DevExpress. –

Respuesta

43

¿Alguna vez has tratado de usar la reflexión? He aquí un fragmento de código de muestra:

// 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

Gracias a abdoul, tu código es bastante fácil de entender. Recientemente tuve un problema al obtener el tipo anónimo y aquí: http: //stackoverflow.com/questions/3534969/only-parameterless-constructors-and-initializers-are-supported-in-linq-to-entitie Dejé la pregunta. Después de buscar y trabajar durante el fin de semana, llegué a esta página y realmente me alegraba el día. – Developer

+0

Eso es exactamente por lo que me encanta SO – Bergkamp

+0

Realmente, la respuesta es demasiado increíble! Esto es lo que estaba buscando desde 2 semanas! ¡Muchas gracias! – KomalJariwala

17

Uno de los problemas con los tipos anónimos es que es difícil usarlos entre funciones. No hay forma de "nombrar" un tipo anónimo y, por lo tanto, es muy difícil elegir entre ellos. Esto evita que se utilicen como expresiones de tipo para todo lo que aparece en los metadatos y está definido por el usuario.

No puedo decir exactamente qué API está utilizando anteriormente. Sin embargo, no es posible que la API devuelva un tipo anónimo fuertemente tipado, por lo que mi conjetura en ese objeto seleccionado se escribe en el objeto. C# 3.0 y siguientes no son compatibles con el acceso dinámico, por lo que no podrá acceder al Id de la propiedad, incluso si está disponible en tiempo de ejecución.

Necesitará uno de los siguientes para evitar este

  • utilizar la reflexión para tomar la propiedad
  • crear un tipo completo y usarlo para rellenar la cuadrícula de datos
  • Utilice uno de los muchos tipo anónimo hacky arroja

EDITAR

He aquí una muestra de cómo hacer un tipo anónimo truco fundido

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 razón es hacky es que es muy fácil de romper este. Por ejemplo, en el método donde se creó originalmente el tipo anónimo. Si agrego otra propiedad al tipo, el código anterior se compilará pero fallará en el tiempo de ejecución.

+0

"tipos anónimos de hacky", ¿qué son esos? – AnthonyWJones

+0

@AnthonyWJones, agregué un ejemplo de un elenco de tipo anónimo hacky – JaredPar

+0

Gracias por esta respuesta. Una solución muy agradable y elegante. Tiene solo un inconveniente: no funciona si el objeto anónimo proviene de otro ensamblaje. Esta es una de las razones por las que nunca debe devolver un objeto anónimo de un método, pero no todos lo saben, así que tengo que lidiar con una biblioteca que desafortunadamente hace exactamente esto. –

0

Esto puede ser incorrecto (es posible que no tenga suficiente código) pero ¿no necesita indexar en la fila para elegir qué columna desea? O si "Id" es la columna que desea, usted debe hacer algo como esto:

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

Ésta es la forma en que me agarro el contenido de una columna en una cuadrícula de datos. Ahora bien, si la columna en sí es de tipo anónimo, entonces no sé, pero si solo está obteniendo una columna con nombre con un tipo primitivo, entonces esto debería funcionar.

1

Como JaredPar adivinó correctamente, el tipo de devolución de GetRow() es object. Cuando se trabaja con la red DevExpress, se podía extraer el valor deseado de esta manera:

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

Este enfoque ha desventajas similares como el "tipo anónimo hacky moldes de" descrito antes: Se necesita una cadena mágica para identificar la columna más una tipo de conversión de objeto a int.

2

Cuando estaba trabajando con el paso de tipos anónimos y tratando de refundirlos, finalmente me pareció más fácil escribir un contenedor que manejaba el trabajo con el objeto. Aquí hay un enlace a una publicación del blog sobre eso.

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

En última instancia, el código sería algo como esto.

//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

Espero que esto ayude, estoy pasando en una lista de interfaces, lo que necesito para obtener una lista distinta de. Primero obtengo una lista de tipo Anónimo y luego la paso para transferirla a mi lista de objetos.

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 solución genérica para obtener el valor de un elemento de datos para una clave dada

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

Ejemplo:

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

Encontré esta solución como la mejor opción para declarar los tipos anónimos. Gracias. – DoomerDGR8

0

Puede recorrer las propiedades de un tipo anónimo como este :

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 El xtraGridView de ss tiene un método como este GetRowCellDisplayText (int rowHandle, columna GridColumn). Con este método, el siguiente código devuelve el id del tipo anónimo.

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

Aunque esto no proporciona una respuesta a la pregunta "¿Cómo puedo obtener acceso a la propiedad del objeto anónimo?", Que todavía intenta resolver la causa raíz del problema.

Intenté esto con la versión 11.1 de devXpress y puedo ver que la pregunta se hizo por primera vez hace casi 2.5 años. Es posible que el autor de la pregunta haya obtenido una solución alternativa o haya encontrado la solución él mismo. Sin embargo, todavía estoy respondiendo para que pueda ayudar a alguien.

11

Puede usar el tipo dinámico para acceder a propiedades de tipos anónimos en tiempo de ejecución sin utilizar el reflejo.

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

Leer más acerca de tipo dinámico aquí: http://msdn.microsoft.com/en-us/library/dd264736.aspx

+0

Tan simple y elegante que me da vergüenza no pensar en ello :) – percebus

0

Si sabe lo que está haciendo y no tienen miedo de conseguir los errores de ejecución cuando los cambios en el código, que podrían emitir sus datos de fila como dynamic:

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

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

No La verificación en tiempo de compilación. Pero debería funcionar bien.

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

Este es el formulario más simple para obtener el valor de los atributos de una lista (DataGridView) –

Cuestiones relacionadas