Comment appeler DynamicObject.TryGetMember directement?
Je suis la mise en œuvre d'un usage général de la fonction pour extraire une valeur d'un arbitraire fourni dynamique de l'objet, mais ne sais pas comment appeler TryGetMember
, car il nécessite un GetMemberBinder
qui est abstrait, donc je ne peut pas le créer.
L'échantillon...
public object GetValue(DynamicObject Source, string FieldName)
{
object Result = null;
GetMemberBinder Binder = x; //What object must be provided?
Binder.Name = FieldName;
if (Source.TryGetMember(Binder, out Result))
return Result;
throw new Exception("The field '" + FieldName + "' not exists");
}
Est-il déjà existante en béton descendant de GetMemberBinder prêt à utiliser? ou un guide pour créer ma propre mise en œuvre?
- Je dois être en manque de quelque chose... n'est-ce pas toute la méthode exactement ce que la dynamique de l'opérateur d'affectation est déjà fait, à l'exception de moins en moins fiable?
- Ma question est au sujet d'obtenir une valeur de champ d'un objet dynamique tout en ne sachant pas à la compilation du temps la façon dont ce champ est nommé. Donc, je ne peux pas le code, par exemple, "var Mavaleur = TheDynamicObject.Le champ;" parce qu'à l'exécution le nom du champ est obtenue. Je suis en train d'écrire un objectif général de classe pour traiter externe fourni des objets dynamiques.
Vous devez vous connecter pour publier un commentaire.
Je ne suis pas sûr s'il y a une méthode dans le cadre qui renvoie en fait un
GetMemberBinder
, mais il n'a pas d'importance - qui n'est pas la bonne façon d'invoquer un membre dynamique par son nom.Ce que vous devez faire est de créer un site d'appel. La méthode ressemble à ceci:
Noter que
Binder.GetMember
crée unCallSiteBinder
, pas unGetMemberBinder
. Juste pour être sur à 100% clair. Cette méthode va jeter unRuntimeBinderException
si l'appel interne àTryGetMember
d'échec, de sorte que vous n'avez pas besoin de vérifier le résultat. Si vous ne voulez pas que les appelants voir leRuntimeBinderException
puis l'envelopper dans votre propre try/catch.Répartition dynamique est complexe, au moins par rapport à la réflexion sur les types statiques. Depuis le CLR n'est pas réellement dynamiquement typé, C# a fait à instancier un compilateur de comprendre comment exécuter le membre/méthode. C'est la création d'un site d'appel. Autant que je sache, vous ont pour ce faire, c'est pourquoi chaque
Binder
méthode retourne unCallSiteBinder
et on ne peut pas instancier une des liants directement.Noter que la RDL ne une sorte de site d'appel de mise en cache, mais je ne suis pas sûr si le système de mise en cache couvre ce scénario. Il ya une bonne chance que vous aurez envie de sauver votre site d'appel pour de futurs appels d'éviter la surcharge de la constante de recompilation.
P. S. Si vous utilisez (ou utiliser)
ExpandoObject
au lieu deDynamicObject
puis garder à l'esprit qu'elle met en œuvreIDictionary<string, object>
, de sorte que vous n'avez pas besoin de faire tout cela. Juste le jeter au type de dictionnaire et de vérifier si la propriété existe. Je n'en ai jamais utiliserDynamicObject
surExpandoObject
si je faisais quelque chose de beaucoup plus compliqué que de simplement ajouter des membres au moment de l'exécution, c'est à dire de changer le comportement réel basé sur le moteur d'exécution de liant.callSite.Target
méthode jette (et sans doute des captures) unRuntimeBinderException
deux fois en fonction de la fenêtre de Sortie, puis renvoie la valeur correcte. Je me demande si en interne il y a quelques méchants try ... catch logique pour arriver membres dynamiques.Vous n'appelez pas TryGetMember directement, ce que vous avez besoin est d'utiliser la dynamique de l'api directement pour obtenir le même effet en utilisant un csharp membre de liant et d'un site d'appel.
C'est d'autant plus facile par le framework open source Dynamitey (via nuget), car il possède une méthode statique qui fait cela. Il fonctionne pour tous les idynamicmetaobjectprovider fournie par pas seulement DynamicObject et (il fonctionne pour les types plus vite que la réflexion trop).