Ma situation est très simple. Quelque part dans mon code, j'ai ceci:
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
//How to do this?
if (myVariable.MyProperty.Exists)
//Do stuff
Donc, fondamentalement, ma question est de savoir comment vérifier (sans lever d'exception) qu'une certaine propriété est disponible sur ma variable dynamique. Je pourrais le faire GetType()
mais je préfère éviter cela car je n'ai pas vraiment besoin de connaître le type d'objet. Tout ce que je veux vraiment savoir, c'est si une propriété (ou une méthode, si cela facilite la vie) est disponible. Des pointeurs?
c#
dynamic
dynamic-keyword
crise circulaire
la source
la source
Réponses:
Je pense qu'il n'y a aucun moyen de savoir si une
dynamic
variable a un certain membre sans essayer d'y accéder, à moins que vous n'ayez réimplémenté la façon dont la liaison dynamique est gérée dans le compilateur C #. Ce qui inclurait probablement beaucoup de suppositions, car il est défini par l'implémentation, selon la spécification C #.Vous devriez donc essayer d'accéder au membre et intercepter une exception, s'il échoue:
la source
IDictionary
et travailler avec cela, cela ne fonctionne que surExpandoObject
, cela ne fonctionnera sur aucun autredynamic
objet.RuntimeBinderException
est dans l'Microsoft.CSharp.RuntimeBinder
espace de noms.Je pensais que je ferais une comparaison de la réponse de Martijn et la réponse de svick ...
Le programme suivant renvoie les résultats suivants:
En conséquence, je suggère d'utiliser la réflexion.Voir ci-dessous.Répondant au commentaire insipide:
Les ratios sont des
reflection:exception
graduations pour 100 000 itérations:... assez juste - si vous vous attendez à ce qu'il échoue avec une probabilité inférieure à ~ 1/47, optez pour l'exception.
Ce qui précède suppose que vous courez à
GetProperties()
chaque fois. Vous pourrez peut-être accélérer le processus en mettant en cache le résultat deGetProperties()
chaque type dans un dictionnaire ou similaire. Cela peut être utile si vous comparez sans cesse le même ensemble de types.la source
IIDynamicMetaObjectProvider
. Je comprends la motivation de votre réponse et je l'apprécie. Il est juste de répondre ainsi.Peut-être utiliser la réflexion?
la source
Where
:.Any(p => p.Name.Equals("PropertyName"))
((Type)myVar.GetType()).GetProperties().Any(x => x.Name.Equals("PropertyName"))
. Le transtypage en type est requis pour rendre le compilateur satisfait du lambda.Juste au cas où cela aiderait quelqu'un:
Si la méthode
GetDataThatLooksVerySimilarButNotTheSame()
renvoie un,ExpandoObject
vous pouvez également transtyper en unIDictionary
avant de vérifier.la source
Les deux solutions courantes à cela incluent l'appel et la capture
RuntimeBinderException
, l'utilisation de la réflexion pour vérifier l'appel, ou la sérialisation au format texte et l'analyse à partir de là. Le problème avec les exceptions est qu'elles sont très lentes, car lorsqu'une est construite, la pile d'appels actuelle est sérialisée. La sérialisation vers JSON ou quelque chose d'analogue entraîne une pénalité similaire. Cela nous laisse avec réflexion mais cela ne fonctionne que si l'objet sous-jacent est en fait un POCO avec de vrais membres dessus. S'il s'agit d'un wrapper dynamique autour d'un dictionnaire, d'un objet COM ou d'un service Web externe, la réflexion n'aidera pas.Une autre solution consiste à utiliser le
DynamicMetaObject
pour obtenir les noms des membres tels que le DLR les voit. Dans l'exemple ci-dessous, j'utilise une classe statique (Dynamic
) pour tester leAge
champ et l'afficher.la source
Dynamitey
paquet nuget le fait déjà. ( nuget.org/packages/Dynamitey )La réponse de Denis m'a fait penser à une autre solution utilisant JsonObjects,
un vérificateur de propriété d'en-tête:
ou peut-être mieux:
par exemple:
la source
Eh bien, j'ai fait face à un problème similaire mais lors de tests unitaires.
En utilisant SharpTestsEx, vous pouvez vérifier si une propriété existe. J'utilise cela pour tester mes contrôleurs, car comme l'objet JSON est dynamique, quelqu'un peut changer le nom et oublier de le changer dans le javascript ou quelque chose, donc tester toutes les propriétés lors de l'écriture du contrôleur devrait augmenter ma sécurité.
Exemple:
Maintenant, en utilisant SharTestsEx:
En utilisant cela, je teste toutes les propriétés existantes en utilisant "Should (). NotThrow ()".
C'est probablement hors sujet, mais peut être utile à quelqu'un.
la source
((string)(testedObject.MyName)).Should().Be("I am a testing object");
À la suite de la réponse de @karask, vous pouvez envelopper la fonction comme une aide comme ceci:
la source
Pour moi, cela fonctionne:
la source
null
ne signifie pas que la propriété n'existe pasSi vous contrôlez le type utilisé comme dynamique, ne pourriez-vous pas retourner un tuple au lieu d'une valeur pour chaque accès à la propriété? Quelque chose comme...
Peut-être une implémentation naïve, mais si vous en construisez une à chaque fois en interne et que vous renvoyez cela au lieu de la valeur réelle, vous pouvez vérifier
Exists
chaque accès à la propriété, puis frapperValue
si c'est le cas avec value étantdefault(T)
(et non pertinent) si ce n'est pas le cas.Cela dit, je manque peut-être des connaissances sur le fonctionnement de la dynamique et ce n'est peut-être pas une suggestion viable.
la source
Dans mon cas, je devais vérifier l'existence d'une méthode avec un nom spécifique, j'ai donc utilisé une interface pour cela
De plus, les interfaces peuvent contenir plus que de simples méthodes:
De: Interfaces (Guide de programmation C #)
Élégant et pas besoin de piéger les exceptions ou de jouer avec la réflexion ...
la source
Je sais que c'est vraiment un ancien post, mais voici une solution simple pour travailler avec
dynamic
taperc#
.la source
Comme
ExpandoObject
hérite du,IDictionary<string, object>
vous pouvez utiliser la vérification suivanteVous pouvez créer une méthode utilitaire pour effectuer cette vérification, qui rendra le code beaucoup plus propre et réutilisable.
la source
Voici l'autre voie:
la source
dynamic
.dynamic
mot-clé est un sujet beaucoup plus large. Allez voir si vous pouvez testerCount
dans cedynamic foo = new List<int>{ 1,2,3,4 }
genre