Eu gostaria de acessar o valor de uma dynamic
propriedade c # com uma string:
dynamic d = new { value1 = "some", value2 = "random", value3 = "value" };
Como posso obter o valor de d.value2 ("aleatório") se eu tenho apenas "value2" como uma string? Em javascript, eu poderia fazer d ["value2"] para acessar o valor ("random"), mas não sei como fazer isso com c # e reflexão. O mais perto que eu cheguei é isso:
d.GetType().GetProperty("value2")
... mas não sei como obter o valor real disso.
Como sempre, obrigado pela sua ajuda!
Respostas:
Depois de obter seu
PropertyInfo
(deGetProperty
), você precisa ligarGetValue
e passar na instância em que deseja obter o valor. No seu caso:fonte
'd.GetType().GetProperty("value2").GetValue(d)' threw an exception of type 'System.Reflection.TargetInvocationException' dynamic {System.Reflection.TargetInvocationException}
na vitrine com isso ..?new {}
cria um tipo anônimo real com propriedades definidas, chamar GetType / GetProperty faz sentido, mas o ExpandoObject, que se você chamar GetType, receberá um tipo que possui as propriedades de ExpandoObject, mas não necessariamente suas propriedades dinâmicas.Adicione referência ao Microsoft.CSharp. Funciona também para tipos dinâmicos e propriedades e campos particulares.
Edit : Enquanto essa abordagem funciona, existe um método quase 20 × mais rápido do assembly Microsoft.VisualBasic.dll :
fonte
d
na pergunta).CallSite
código vsCallByName
código, você comparou os dois enquanto fazia o cache daCallSite
instância? Eu suspeito que o custo do seu primeiro método é quase puramente a ativação doBinder
eCallSite
, não a invocaçãoTarget()
Dynamitey é uma
.net std
biblioteca de código-fonte aberto , que você pode chamá-la como adynamic
palavra - chave, mas usando a string a para o nome da propriedade em vez do compilador fazendo isso por você, e acaba sendo igual à reflexão em velocidade (o que não é tão rápido como usar a palavra-chave dinâmica, mas isso ocorre devido à sobrecarga extra do armazenamento em cache dinamicamente, onde o compilador armazena em cache estaticamente).fonte
O método mais fácil para obter a
setter
e agetter
para uma propriedade que funcione para qualquer tipo, incluindodynamic
eExpandoObject
é usar,FastMember
que também é o método mais rápido (usa Emit).Você pode obter uma
TypeAccessor
baseada em um determinado tipo ouObjectAccessor
uma instância de um determinado tipo.Exemplo:
fonte
Na maioria das vezes, quando você solicita um objeto dinâmico, obtém um ExpandoObject (não no exemplo anônimo, mas estático, da pergunta acima, mas menciona JavaScript e meu analisador JSON JsonFx escolhido, por exemplo, gera ExpandoObjects).
Se sua dinâmica é de fato um ExpandoObject, você pode evitar a reflexão convertendo-a no IDictionary, conforme descrito em http://msdn.microsoft.com/en-gb/library/system.dynamic.expandoobject.aspx .
Depois de converter para o IDictionary, você terá acesso a métodos úteis como .Item e .ContainsKey
fonte
Int64? i = data.value; //data is ExpandoObject
automaticamente e chamaria o operador implícito. Por outro lado, se eu tivesse que usar o IDictionary para testar se o campo "valor" existe, eu recuperaria um objeto que não será convertido sem erro no Int64 ?.O GetProperty / GetValue não funciona para dados Json, sempre gera uma exceção nula; no entanto, você pode tentar esta abordagem:
Serialize seu objeto usando JsonConvert:
Em seguida, acesse-o diretamente, lançando-o de volta à string:
Pode funcionar diretamente aplicando o Convert.ToString (request) ["DynamicFieldName"], porém não testei.
fonte
new JavaScriptSerializer().Deserialize<object>(json);
para chegar às "propriedades" da maneira que você sugeriuretorna um objeto PropertyInfo.
Então faça
fonte
GetValue(d)
necessidades devem serGetValue(d,null)
Esta é a maneira como obtive o valor de um valor de propriedade de um dinâmico:
fonte
Para obter propriedades do documento dinâmico quando
.GetType()
retornarnull
, tente o seguinte:fonte
No .Net core 3.1, você pode tentar assim
fonte
Semelhante à resposta aceita, você também pode tentar em
GetField
vez deGetProperty
.d.GetType().GetField("value2").GetValue(d);
Dependendo de como o real
Type
foi implementado, isso pode funcionar quando GetProperty () não e pode ser ainda mais rápido.fonte