Como eu reflito sobre os membros do objeto dinâmico?
Preciso obter um dicionário de propriedades e seus valores de um objeto declarado com a palavra-chave dinâmica no .NET 4? Parece que usar a reflexão para isso não funcionará.
— Flatliner DOA
Se o IDynamicMetaObjectProvider puder fornecer os nomes de membros dinâmicos, você poderá obtê-los. Veja a implementação de GetMemberNames na biblioteca PCL licenciada do apache Dynamitey (que pode ser encontrada em nuget), ela funciona para ExpandoObjects e DynamicObjects que implementam GetDynamicMemberNamese para qualquer outro IDynamicMetaObjectProviderque fornece um metaobjeto com uma implementação GetDynamicMemberNamessem testes personalizados além is IDynamicMetaObjectProvider.
Depois de obter os nomes dos membros, é um pouco mais trabalhoso obter o valor da maneira certa, mas o Impromptu faz isso, mas é mais difícil apontar apenas os bits interessantes e fazer com que faça sentido. Aqui está a documentação e é igual ou mais rápida que a reflexão; no entanto, é improvável que seja mais rápida que uma pesquisa no dicionário para expando, mas funciona para qualquer objeto, expando, dinâmico ou original - você escolhe.
— jbtule
Graças a esse ponto, o código é: var tTarget = target as IDynamicMetaObjectProvider; if (tTarget! = null) {tList.AddRange (tTarget.GetMetaObject (Expression.Constant (tTarget)). GetDynamicMemberNames ()); }
obrigado pela sua ótima biblioteca. Eu estava com problemas para fazer um round-trip de um objeto dinâmico para esta biblioteca dynamicjson.codeplex.com e pude estendê -lo com sua biblioteca.
— JJS 30/07
— Demodave
No caso de ExpandoObject, a classe ExpandoObject realmente implementa IDictionary<string, object>suas propriedades, portanto a solução é tão trivial quanto a conversão:
IDictionary<string, object> propertyValues = (IDictionary<string, object>)s;
Observe que isso não funcionará para objetos dinâmicos gerais. Nesses casos, você precisará ir para o DLR via IDynamicMetaObjectProvider.
Obrigado por isso, infelizmente a amostra foi um pouco simplificada. Eu preciso ser capaz de inspecionar um objeto dinâmico sem saber qual é o seu tipo real.
Isso funciona apenas para objetos da classe ExpandoObject, a classe DynamicObject é outra classe extensível que não implementa o IDictionary, mas implementa o IDynamicMetaObjectProvider.
Porém, ele responde à pergunta do OP.
Existem vários cenários a serem considerados. Primeiro de tudo, você precisa verificar o tipo do seu objeto. Você pode simplesmente chamar GetType () para isso. Se o tipo não implementar IDynamicMetaObjectProvider, você poderá usar a mesma reflexão de qualquer outro objeto. Algo como:
No entanto, para implementações IDynamicMetaObjectProvider, a reflexão simples não funciona. Basicamente, você precisa saber mais sobre esse objeto. Se for ExpandoObject (que é uma das implementações IDynamicMetaObjectProvider), você poderá usar a resposta fornecida por itowlson. ExpandoObject armazena suas propriedades em um dicionário e você pode simplesmente converter seu objeto dinâmico em um dicionário.
Se for DynamicObject (outra implementação de IDynamicMetaObjectProvider), será necessário usar quaisquer métodos que este DynamicObject exponha. O DynamicObject não é necessário para "armazenar" realmente sua lista de propriedades em qualquer lugar. Por exemplo, pode ser algo como isto (estou reutilizando um exemplo da minha postagem no blog ):
Nesse caso, sempre que você tentar acessar uma propriedade (com qualquer nome), o objeto simplesmente retornará o nome da propriedade como uma sequência.
Portanto, você não tem nada para refletir - esse objeto não possui propriedades e, ao mesmo tempo, todos os nomes de propriedades válidos funcionarão.
Eu diria que para implementações IDynamicMetaObjectProvider, você precisa filtrar implementações conhecidas, onde pode obter uma lista de propriedades, como ExpandoObject, e ignorar (ou lançar uma exceção) para o resto.
— Alexandra Rusina
Parece-me que, se o tipo que eu consumir é Dinâmico, não devo fazer suposições sobre o tipo subjacente. Eu devo chamar GetDynamicMemberNames para obter a lista de membros. Parece estúpido que os tipos estáticos tenham melhor suporte à inspeção em tempo de execução do que os dinâmicos!
Você pode substituir o método GetDynamicMemberNames () de um objeto dinâmico para retornar os nomes da lista de membros dinâmicos. O problema é que não é garantido que todo objeto dinâmico possua esse método (o ExpandoObject não possui). Não é de surpreender que a reflexão funcione melhor para tipos estáticos. Foi criado para eles em primeiro lugar. Com a dinâmica, você precisa confiar mais em testes de unidade e TDD.
A documentação do MSDN para GetDynamicMemberNames () menciona: "existe Este método somente para fins de depuração.", Não é realmente confortante :(
Requer Newtonsoft Json.Net
Um pouco tarde, mas eu vim com isso. Ele fornece apenas as chaves e você pode usá-las na dinâmica:
public List<string> GetPropertyKeysForDynamic(dynamic dynamicToGetPropertiesFor)
JObject attributesAsJObject = dynamicToGetPropertiesFor;
toReturn.Add(key);
Então você simplesmente projeta assim:
foreach(string propertyName in GetPropertyKeysForDynamic(dynamicToGetPropertiesFor))
dynamic/object/string propertyValue = dynamicToGetPropertiesFor[propertyName];
dynamicToGetPropertiesFor[propertyName] = "Your Value"; // Or an object value
Optando por obter o valor como uma sequência ou outro objeto, ou faça outra dinâmica e use a pesquisa novamente.
Você não precisa da lista para retornar.
— aloisdg movendo-se para codidact.com 16/11
Perfeito! Eu tive que mudar JObject attributeAsJObject = dynamicToGetPropertiesFor; para Object attributeAsJObject = (JObject) JToken.FromObject (obj); Apesar!!
Apenas para reiterar o que o @ k25 disse. É necessário substituir JObject attributesAsJObject = dynamicToGetPropertiesFor;com algo como: var jObject = (JObject) JToken.FromObject(dynamicToGetPropertiesFor);. Nesse ponto, você pode obter um dicionário de nomes e valores de propriedades fazendo algo parecido var objProperties = jObject.ToObject<Dictionary<string, object>>();. Com isso em mãos, você está pronto para as corridas. Isso não precisa de uma dinâmica. Ele funciona bem com qualquer coisa que é uma subclasse deDynamicObject