Me gustaría acceder al valor de una dynamic
propiedad de C # con una cadena:
dynamic d = new { value1 = "some", value2 = "random", value3 = "value" };
¿Cómo puedo obtener el valor de d.value2 ("random") si solo tengo "value2" como una cadena? En javascript, podría hacer d ["value2"] para acceder al valor ("random"), pero no estoy seguro de cómo hacerlo con c # y la reflexión. Lo más cerca que he venido es esto:
d.GetType().GetProperty("value2")
... pero no sé cómo obtener el valor real de eso.
Como siempre, gracias por tu ayuda!
Respuestas:
Una vez que tenga su
PropertyInfo
(desdeGetProperty
), debe llamarGetValue
y pasar la instancia de la que desea obtener el valor. En tu caso:fuente
'd.GetType().GetProperty("value2").GetValue(d)' threw an exception of type 'System.Reflection.TargetInvocationException' dynamic {System.Reflection.TargetInvocationException}
en la ventana del reloj con eso ...?new {}
crea un tipo anónimo real con propiedades definidas, llamar a GetType / GetProperty tiene sentido, pero qué pasa con ExpandoObject, que si llama a GetType, obtendrá un tipo que tiene las propiedades de ExpandoObject, pero no necesariamente sus propiedades dinámicas.Agregar referencia a Microsoft.CSharp. Funciona también para tipos dinámicos y propiedades y campos privados.
Editar : Si bien este enfoque funciona, hay un método casi 20 veces más rápido del ensamblado Microsoft.VisualBasic.dll :
fuente
d
en la pregunta).CallSite
código frente alCallByName
código, ¿comparó los dos al almacenar en caché laCallSite
instancia? Sospecho que el costo de su primer método es casi puramente la activación deBinder
yCallSite
, no la invocación deTarget()
Dynamitey es una
.net std
biblioteca de código abierto , que le permite llamarla como ladynamic
palabra clave, pero usando una cadena para el nombre de la propiedad en lugar del compilador que lo hace por usted, y termina siendo igual a la velocidad de reflexión (que no es tan rápido) como el uso de la palabra clave dinámica, pero esto se debe a la sobrecarga adicional de almacenamiento en caché de forma dinámica, donde el compilador almacena en caché de forma estática).fuente
El método más fácil para obtener a
setter
y agetter
para una propiedad que funciona para cualquier tipo, incluidodynamic
yExpandoObject
es usar,FastMember
que también es el método más rápido (usa Emit).Puede obtener una
TypeAccessor
base de un tipo determinado o unaObjectAccessor
base de una instancia de un tipo determinado.Ejemplo:
fuente
La mayoría de las veces, cuando solicita un objeto dinámico, obtiene un Objeto de Expando (no en el ejemplo de la pregunta anónimo, pero estáticamente escrito anteriormente, pero menciona JavaScript y mi analizador JSON elegido JsonFx, por ejemplo, genera ExpandoObjects).
Si su dinámica es, de hecho, un Objeto de Expando, puede evitar la reflexión lanzándola a IDictionary, como se describe en http://msdn.microsoft.com/en-gb/library/system.dynamic.expandoobject.aspx .
Una vez que ha enviado a IDictionary, tiene acceso a métodos útiles como .Item y .ContainsKey
fuente
Int64? i = data.value; //data is ExpandoObject
buscaría automáticamente y llamaría al operador implícito. Por otro lado, si tuviera que usar IDictionary para probar si existe el campo "valor", obtendría un objeto que no se lanzará sin error a Int64.GetProperty / GetValue no funciona para datos Json, siempre genera una excepción nula, sin embargo, puede probar este enfoque:
Serialice su objeto usando JsonConvert:
Luego, acceda directamente a él, volviéndolo a la cadena:
Puede funcionar directamente aplicando Convert.ToString (solicitud) ["DynamicFieldName"], sin embargo, no lo he probado.
fuente
new JavaScriptSerializer().Deserialize<object>(json);
para llegar a las "propiedades" de la manera que sugiriódevuelve un objeto PropertyInfo.
Entonces hazlo
fuente
GetValue(d)
necesidad debe serGetValue(d,null)
Esta es la forma en que obtuve el valor de un valor de propiedad de una dinámica:
fuente
Para obtener propiedades del documento dinámico cuando
.GetType()
regresanull
, intente esto:fuente
En .Net core 3.1 puedes probar así
fuente
Similar a la respuesta aceptada, también puede intentar en
GetField
lugar deGetProperty
.d.GetType().GetField("value2").GetValue(d);
Dependiendo de cómo
Type
se implementó el actual , esto puede funcionar cuando GetProperty () no lo hace e incluso puede ser más rápido.fuente