Minha situação é muito simples. Em algum lugar do meu código, tenho o seguinte:
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
//How to do this?
if (myVariable.MyProperty.Exists)
//Do stuff
Então, basicamente, minha pergunta é como verificar (sem gerar uma exceção) se uma determinada propriedade está disponível na minha variável dinâmica. Eu poderia fazer, GetType()
mas prefiro evitar isso, já que realmente não preciso saber o tipo do objeto. Tudo o que eu realmente quero saber é se uma propriedade (ou método, se isso facilita a vida) está disponível. Alguma dica?
c#
dynamic
dynamic-keyword
roundcrisis
fonte
fonte
Respostas:
Eu acho que não há como descobrir se uma
dynamic
variável tem um determinado membro sem tentar acessá-la, a menos que você reimplemente a maneira como a ligação dinâmica é tratada no compilador C #. O que provavelmente incluiria muita adivinhação, porque é definido pela implementação, de acordo com a especificação C #.Portanto, você deve realmente tentar acessar o membro e capturar uma exceção, se falhar:
fonte
IDictionary
e trabalhar com isso, isso só funcionaExpandoObject
, não funcionará em nenhum outrodynamic
objeto.RuntimeBinderException
está noMicrosoft.CSharp.RuntimeBinder
espaço para nome.Pensei em fazer uma comparação da resposta de Martijn e resposta de svick ...
O programa a seguir retorna os seguintes resultados:
Como resultado, eu sugiro usar a reflexão.Ver abaixo.Respondendo ao comentário de Bland:
As proporções são
reflection:exception
marcações para 100000 iterações:... justo o suficiente - se você espera que falhe com uma probabilidade inferior a ~ 1/47, procure a exceção.
O acima pressupõe que você esteja executando
GetProperties()
cada vez. Você pode acelerar o processo armazenando em cache o resultado deGetProperties()
cada tipo em um dicionário ou similar. Isso pode ajudar se você estiver verificando o mesmo conjunto de tipos repetidamente.fonte
IIDynamicMetaObjectProvider
. Entendo a motivação por trás da sua resposta e agradeço. É justo responder isso.Talvez use reflexão?
fonte
Where
:.Any(p => p.Name.Equals("PropertyName"))
((Type)myVar.GetType()).GetProperties().Any(x => x.Name.Equals("PropertyName"))
. A conversão de tipo é necessária para deixar o compilador satisfeito com o lambda.Apenas no caso de ajudar alguém:
Se o método
GetDataThatLooksVerySimilarButNotTheSame()
retornar um,ExpandoObject
você também poderá converter para aIDictionary
antes de verificar.fonte
As duas soluções comuns para isso incluem fazer a chamada e capturar o
RuntimeBinderException
, usar reflexão para verificar a chamada ou serializar para um formato de texto e analisar a partir daí. O problema das exceções é que elas são muito lentas, porque quando uma é construída, a pilha de chamadas atual é serializada. Serializar para JSON ou algo análogo incorre em uma penalidade semelhante. Isso nos deixa com reflexão, mas só funciona se o objeto subjacente for realmente um POCO com membros reais. Se for um invólucro dinâmico em torno de um dicionário, um objeto COM ou um serviço da Web externo, a reflexão não ajudará.Outra solução é usar o
DynamicMetaObject
para obter os nomes dos membros conforme o DLR os vê. No exemplo abaixo, eu uso uma classe estática (Dynamic
) para testar oAge
campo e exibi-lo.fonte
Dynamitey
pacote nuget já faz isso. ( Nuget.org/packages/Dynamitey )A resposta de Denis me fez pensar em outra solução usando JsonObjects,
um verificador de propriedade do cabeçalho:
ou talvez melhor:
por exemplo:
fonte
Bem, eu enfrentei um problema semelhante, mas em testes de unidade.
Usando o SharpTestsEx, você pode verificar se existe uma propriedade. Uso esse teste em meus controladores, porque, como o objeto JSON é dinâmico, alguém pode alterar o nome e esquecer de alterá-lo no javascript ou algo assim, portanto, testar todas as propriedades ao escrever o controlador deve aumentar minha segurança.
Exemplo:
Agora, usando SharTestsEx:
Usando isso, testo todas as propriedades existentes usando "Should (). NotThrow ()".
Provavelmente está fora de tópico, mas pode ser útil para alguém.
fonte
((string)(testedObject.MyName)).Should().Be("I am a testing object");
Seguindo a resposta de @karask, você pode agrupar a função como um auxiliar da seguinte maneira:
fonte
Para mim, isso funciona:
fonte
null
não significa que a propriedade não existeSe você controlar o tipo que está sendo usado como dinâmico, não poderá retornar uma tupla em vez de um valor para cada acesso à propriedade? Algo como...
Possivelmente uma implementação ingênua, mas se você construir uma delas internamente a cada vez e retornar isso em vez do valor real, poderá verificar
Exists
todos os acessos à propriedade e, em seguida, clicarValue
se isso ocorrer com o valor sendodefault(T)
(e irrelevante) se isso não acontecer.Dito isto, posso estar perdendo algum conhecimento sobre como a dinâmica funciona e isso pode não ser uma sugestão viável.
fonte
No meu caso, eu precisava verificar a existência de um método com um nome específico, então usei uma interface para isso
Além disso, as interfaces podem conter mais do que apenas métodos:
De: Interfaces (Guia de Programação em C #)
Elegante e sem necessidade de capturar exceções ou brincar com reflexões ...
fonte
Eu sei que esse post é realmente antigo, mas aqui está uma solução simples para trabalhar com o
dynamic
tipoc#
.fonte
Como
ExpandoObject
herda,IDictionary<string, object>
você pode usar a seguinte verificaçãoVocê pode criar um método utilitário para executar essa verificação, que tornará o código muito mais limpo e reutilizável
fonte
Aqui está o outro caminho:
fonte
dynamic
.dynamic
palavra-chave é um assunto muito mais amplo. Verificação Go se você pode testar paraCount
emdynamic foo = new List<int>{ 1,2,3,4 }
como essa