2012-09-28 14 views
6

Estoy obteniendo una lista de las listas de comercialización. Mientras lo hago, parece ser una operación exitosa de acuerdo con mi control usando intellisense. Cuando busco ...Entities[0].Attributes["nick"] obtengo un objeto (con los datos correctos en algún lugar). Pero no puedo acceder a él programáticamente (en su lugar, tengo que hacer clic como un mono a través de las ventajas para desplegar las cosas buenas).¿Cómo acceder a los valores de fetchedXML cuando se usan alias para los atributos en CRM Dynamics?

De hecho, estoy obteniendo las entidades que supuestamente usan el siguiente código. El problema es que no son Strings según la computadora. Son del tipo Microsoft.Xrm.Sdk.AliasedValue y no sé cómo acceder al nick actual dentro de ellos.

new Contact 
{ 
    Name = element.Attributes["nick"] as String, 
    Mail = element.Attributes["mail"] as String 
} 

Intellisense dice que es Value allí (y es el valor correcto también), pero no puedo acceder a él escribiendo .Value. Sospecho que necesito usar "como" o algo así, pero en este momento estoy atascado. ¿Algún consejo? As 'ing a String, que se supone que funciona, me da null ...

He leído this article y varios otros como él y la forma en que lo veo, se supone que debo ser capaz de acceder a todos las cosas divertidas allí. No puedo aunque ...

He notado que el siguiente código me da los datos que estoy tratando desesperadamente de obtener pero este no puede ser una sintaxis profesional, ¿o sí? En serio, se ve como un estudiante de secundaria con TDAH y la resaca trató de hacer eso ...

new Contact 
{ 
    Name = ((Microsoft.Xrm.Sdk.AliasedValue)result.Entities[0].Attributes["nick"]).Value, 
    Mail = ((Microsoft.Xrm.Sdk.AliasedValue)result.Entities[0].Attributes["mail"]).Value 
} 

Quiero decir, en serio - se trata de una pieza de código feo ... Tiene que haber una manera mejor! Sin embargo, me temo que no se debe a this discussion parece estar usando la sintaxis, así ...

+0

No hay nada malo con el elenco –

+0

@JamesWood Jaja, dicen que a mi antiguo profesor en la Universidad. "Si necesitas lanzar, tienes un mal diseño. ¡Hecho!" Creo que estaba en lo cierto en que ** en algunos casos ** el casting ** es ** correcto, pero probablemente culparía a Microsoft en este caso. Fue en los años 90 cuando Java era el niño de oro y el único camino a seguir. MS era malvado y un engendro de Satanás, jaja. –

+0

Bueno, si no quieres lanzar, puedes usar las entidades fuertemente tipadas. El objetivo de la Entidad con límite de tiempo es permitirle ser flexible, lo que en este caso significa que tiene que lanzar de vez en cuando. También en este caso, no estás lanzando para cambiar el objeto (por ejemplo, int a decimal), estás lanzando para que tengas acceso a todas las propiedades. –

Respuesta

7

Mirando el documention, la propiedad del objeto AttributesEntity es de tipo AttributeCollection, que deriva de DataCollection<string,Object>.

Para cada atributo en la colección hay un par de clave/valor.

Así que para cada tecla ("nick", "mail"), hay una correspondiente object, que podría ser de cualquier tipo .NET. Usted tiene para convertir el objeto al tipo correcto (como lo ha hecho) para acceder a las propiedades que está buscando (o bien use reflection, que sin duda sería más feo, o supongo que en C# 4.0 el dynamic type, pero en ese caso, pierde la verificación en tiempo de compilación); ¿De qué otro modo podría el compilador determinar si un atributo es del tipo string/Money/int/AliasedValue/etc.?

En cuanto a AliasedValue, el CRM utiliza este tipo para almacenar información adicional sobre el valor devuelto, y desde cualquier atributo puede tener un alias, la propiedad Value podría ser de cualquier tipo (OptionSetValue, decimal, string, Guid, EntityReference, etc. .). La propiedad Value es apropiada también del tipo object, por lo que debe incluirla para obtener información adicional sobre el valor devuelto.

Así que no hay manera alrededor de la fundición, pero se puede hacer que el código más corto y quizás más limpio mediante la adición de una declaración using en la parte superior de su archivo y la definición de los valores de cada AliasedValue antes de la asignación al Contact. Independientemente, he incluido un ejemplo de cada tipo de recuperación de datos; puedes juzgar cuál es mejor en tu proyecto.

El uso de fundición:

using Microsoft.Xrm.Sdk; 

... 

var nick = (AliasedValue)result.Entities[0].Attributes["nick"]; 
var mail = (AliasedValue)result.Entities[0].Attributes["mail"]; 

var contact = new Contact 
{ 
    Name = nick.Value, //Value is of type object; cast again for a more specific type 
    Mail = mail.Value 
}; 

El uso de la reflexión:

var nick = result.Entities[0].Attributes["nick"] 
    .GetType() 
    .GetProperty("Value") 
    .GetValue(result.Entities[0].Attributes["nick"], null); 
var mail = result.Entities[0].Attributes["mail"] 
    .GetType() 
    .GetProperty("Value") 
    .GetValue(result.Entities[0].Attributes["mail"], null); 

var contact = new Contact 
{ 
    Name = nick, 
    Mail = mail 
}; 

Usando dinámica:

dynamic nick = result.Entities[0].Attributes["nick"]; 
dynamic mail = result.Entities[0].Attributes["mail"]; 

var contact = new Contact 
{ 
    Name = nick.Value, //dynamic figures out the right property at runtime 
    Mail = mail.Value 
}; 
+0

Oh, eso estuvo bien. No estoy encantado, pero sigue siendo bueno. De alguna manera, me siento satisfecho de que ** mi ** enfoque (por feo que sea) fue el recomendado por otros. Lo conservaré ya que es la manera más rápida. +1 por todo lo anterior. Mereces obtener más, pero las reglas SO son como son. En cuanto al 'uso', lo tengo en mi código. Aquí utilicé el camino completo para hacer un punto. –

Cuestiones relacionadas