2012-09-28 12 views
6

Sto recuperando un elenco di elenchi di marketing. Mentre lo faccio, sembra essere un'operazione di successo secondo il mio controllo usando intellisense. Quando cerco ...Entities[0].Attributes["nick"] ottengo un oggetto (con i dati corretti da qualche parte). Ma non posso accedervi a livello di programmazione (invece devo cliccare in giro come una scimmia tramite i vantaggi per ripiegare le cose buone).Come accedere ai valori da fetchedXML quando si utilizzano alias per gli attributi in CRM Dynamics?

Infatti, sto ottenendo che le entità utilizzino il codice riportato di seguito. Il problema è che non sono Strings secondo il computer. Sono di tipo Microsoft.Xrm.Sdk.AliasedValue e non so come accedere al nick reale al loro interno.

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

Intellisense dice che Value è lì (ed è il valore corretto troppo), ma non possono accedere digitando .Value. Sospetto che dovrei usare "come" o qualcosa del genere ma al momento sono bloccato. Qualche suggerimento? As 'ing a String, che dovrebbe lavorare, mi dà null ...

Ho letto this article e molti altri come esso e il modo in cui la vedo io, dovrei essere in grado di accedere a tutti le cose divertenti lì dentro Non posso però ...

Ho notato che il codice seguente mi fornisce i dati che sto cercando disperatamente di ottenere ma questo non può essere una sintassi professionale, vero ?! Scherzi a parte, sembra uno studente di liceo con ADHD e sbornia cercato di farlo ...

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

Voglio dire, sul serio - questo è un brutto pezzo di codice ... Ci deve essere un modo migliore! Temo, tuttavia, che non c'è perché this discussion sembra essere utilizzando la sintassi che oltre ...

+0

c'è niente di sbagliato con il cast –

+0

@JamesWood Haha, dicono che per il mio ex professore all'università. "Se hai bisogno di un cast, hai un cattivo design. Immagino che avessi ragione che ** in alcuni casi ** il casting ** è ** corretto, ma probabilmente in questo caso sarebbe la colpa di Microsoft. Era negli anni '90 quando Java era il bambino d'oro e l'unica strada da percorrere. La SM era malvagia e una progenie di Satana, haha. –

+0

Beh, se non vuoi cast puoi usare le entità fortemente tipizzate. Il punto dell'entità legata in ritardo è quello di consentire di essere flessibili, che in questo caso significa che devi lanciare una volta ogni tanto. Anche in questo caso non stai lanciando per cambiare l'oggetto (ad esempio int to decimal), stai trasmettendo in modo da avere accesso a tutte le proprietà. –

risposta

7

Guardando il documention, la proprietà dell'oggetto EntityAttributes è di tipo AttributeCollection, che deriva da DataCollection<string,Object>.

Per ogni attributo nella raccolta è presente una coppia chiave/valore.

Quindi per ogni chiave ("nick", "mail"), c'è un corrispondente object, che potrebbe essere di qualsiasi tipo .NET. È avere per trasmettere l'oggetto al tipo corretto (come hai fatto) per accedere alle proprietà che stai cercando (oppure usare reflection, che sarebbe certamente più brutto, o suppongo in C# 4.0 il dynamic type, ma in tal caso, si perde il controllo in fase di compilazione); in quale altro modo il compilatore è in grado di determinare se un attributo è di tipo //AliasedValue/ecc.?

Per quanto riguarda AliasedValue, il CRM utilizza questo tipo di memorizzare ulteriori informazioni sul valore restituito, e dal momento che qualsiasi attributo può essere aliasing, la proprietà Value potrebbe essere di qualsiasi tipo (OptionSetValue, decimal, string, Guid, EntityReference, ecc .). La proprietà Value è quindi opportunamente anche di tipo object, quindi è necessario eseguire il cast anche per ottenere ulteriori informazioni sul valore restituito.

Quindi non c'è modo per aggirare casting, ma si può rendere il codice più breve e forse più pulito con l'aggiunta di una dichiarazione using nella parte superiore del file e definendo i valori di ogni AliasedValue prima della cessione al Contact. Indipendentemente da ciò, ho incluso un esempio di ciascun tipo di recupero dei dati; puoi giudicare quale è meglio nel tuo progetto.

Utilizzando casting:

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

riflessione Usando:

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

Utilizzando dinamica:

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, è stato bello. Non sono contento ma è comunque bello. In un certo senso mi sento soddisfatto del fatto che ** il mio ** approccio (brutto che sia) sia stato raccomandato da altri. Lo terrò poiché è il modo più veloce. +1 per tutto quanto sopra. Ti meriti di ottenere di più ma SO governa come sono. Per quanto riguarda l'uso, lo ho nel mio codice. Qui ho usato il percorso completo per fare un punto. –