Meine Situation ist sehr einfach. Irgendwo in meinem Code habe ich Folgendes:
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
//How to do this?
if (myVariable.MyProperty.Exists)
//Do stuff
Meine Frage ist also im Grunde, wie ich überprüfen kann (ohne eine Ausnahme auszulösen), ob eine bestimmte Eigenschaft für meine dynamische Variable verfügbar ist. Ich könnte es tun, GetType()
aber ich würde das lieber vermeiden, da ich den Typ des Objekts nicht wirklich kennen muss. Alles, was ich wirklich wissen möchte, ist, ob eine Eigenschaft (oder eine Methode, wenn das das Leben leichter macht) verfügbar ist. Irgendwelche Hinweise?
c#
dynamic
dynamic-keyword
Rundkrise
quelle
quelle
Antworten:
Ich denke, es gibt keine Möglichkeit herauszufinden, ob eine
dynamic
Variable ein bestimmtes Mitglied hat, ohne zu versuchen, darauf zuzugreifen, es sei denn, Sie haben die Art und Weise, wie die dynamische Bindung im C # -Compiler behandelt wird, erneut implementiert. Dies würde wahrscheinlich viel Vermutung beinhalten, da es gemäß der C # -Spezifikation implementierungsdefiniert ist.Sie sollten also tatsächlich versuchen, auf das Mitglied zuzugreifen und eine Ausnahme abzufangen, wenn dies fehlschlägt:
quelle
IDictionary
und Arbeiten damit meinen , funktioniert das nur beiExpandoObject
, es funktioniert bei keinem anderendynamic
Objekt.RuntimeBinderException
ist imMicrosoft.CSharp.RuntimeBinder
Namespace.Ich dachte, ich würde Martijns Antwort und Svicks Antwort vergleichen ...
Das folgende Programm gibt die folgenden Ergebnisse zurück:
Daher würde ich vorschlagen, Reflexion zu verwenden.Siehe unten.Auf Blands Kommentar antworten:
Verhältnisse sind
reflection:exception
Ticks für 100000 Iterationen:... fair genug - wenn Sie erwarten, dass es mit einer Wahrscheinlichkeit von weniger als ~ 1/47 fehlschlägt, dann gehen Sie zur Ausnahme.
Das oben Gesagte setzt voraus, dass Sie
GetProperties()
jedes Mal laufen . Möglicherweise können Sie den Prozess beschleunigen, indem Sie das ErgebnisGetProperties()
für jeden Typ in einem Wörterbuch oder ähnlichem zwischenspeichern. Dies kann hilfreich sein, wenn Sie immer wieder mit denselben Typen vergleichen.quelle
IIDynamicMetaObjectProvider
. Ich verstehe die Motivation hinter Ihrer Antwort und schätze sie. Es ist fair, so zu antworten.Vielleicht Reflexion verwenden?
quelle
Where
:.Any(p => p.Name.Equals("PropertyName"))
((Type)myVar.GetType()).GetProperties().Any(x => x.Name.Equals("PropertyName"))
. Die Umwandlung in Typ ist erforderlich, um den Compiler über das Lambda glücklich zu machen.Nur für den Fall, dass es jemandem hilft:
Wenn die Methode eine
GetDataThatLooksVerySimilarButNotTheSame()
zurückgibtExpandoObject
, können Sie dieseIDictionary
vor der Überprüfung auch in a umwandeln.quelle
Die beiden gängigen Lösungen hierfür sind das Tätigen und Abfangen des Anrufs, das
RuntimeBinderException
Verwenden der Reflexion zum Überprüfen des Anrufs oder das Serialisieren in ein Textformat und das Parsen von dort aus. Das Problem mit Ausnahmen ist, dass sie sehr langsam sind, da bei der Erstellung der aktuelle Aufrufstapel serialisiert wird. Die Serialisierung auf JSON oder etwas Ähnliches führt zu einer ähnlichen Strafe. Dies lässt uns nachdenken, funktioniert aber nur, wenn das zugrunde liegende Objekt tatsächlich ein POCO mit echten Mitgliedern ist. Wenn es sich um einen dynamischen Wrapper um ein Wörterbuch, ein COM-Objekt oder einen externen Webdienst handelt, hilft die Reflexion nicht weiter.Eine andere Lösung besteht darin
DynamicMetaObject
, die Mitgliedsnamen so zu ermitteln, wie sie vom DLR angezeigt werden. Im folgenden Beispiel verwende ich eine statische Klasse (Dynamic
), um dasAge
Feld zu testen und anzuzeigen.quelle
Dynamitey
Nuget-Paket dies bereits tut. ( nuget.org/packages/Dynamitey )Die Antwort von Denis ließ mich über eine andere Lösung mit JsonObjects nachdenken.
ein Header-Eigenschaftsprüfer:
oder vielleicht besser:
beispielsweise:
quelle
Nun, ich hatte ein ähnliches Problem, aber bei Unit-Tests.
Mit SharpTestsEx können Sie überprüfen, ob eine Eigenschaft vorhanden ist. Ich verwende diese Tests, um meine Controller zu testen, da das JSON-Objekt dynamisch ist und jemand den Namen ändern und vergessen kann, ihn im Javascript oder so zu ändern. Daher sollte das Testen aller Eigenschaften beim Schreiben des Controllers meine Sicherheit erhöhen.
Beispiel:
Verwenden Sie jetzt SharTestsEx:
Damit teste ich alle vorhandenen Eigenschaften mit "Should (). NotThrow ()".
Es ist wahrscheinlich nicht zum Thema, kann aber für jemanden nützlich sein.
quelle
((string)(testedObject.MyName)).Should().Be("I am a testing object");
In Anlehnung an die Antwort von @karask können Sie die Funktion als Helfer wie folgt umschließen:
quelle
Bei mir funktioniert das:
quelle
null
bedeutet nicht, dass die Eigenschaft nicht existiertWenn Sie den als dynamisch verwendeten Typ steuern, können Sie dann nicht für jeden Eigenschaftszugriff ein Tupel anstelle eines Werts zurückgeben? Etwas wie...
Möglicherweise eine naive Implementierung, aber wenn Sie jedes Mal eine davon intern erstellen und diese anstelle des tatsächlichen Werts zurückgeben, können Sie
Exists
jeden Eigenschaftszugriff überprüfen und dann drücken,Value
ob dies der Fall istdefault(T)
(und irrelevant), wenn dies nicht der Fall ist.Trotzdem fehlt mir möglicherweise etwas Wissen darüber, wie Dynamik funktioniert, und dies ist möglicherweise kein praktikabler Vorschlag.
quelle
In meinem Fall musste ich prüfen, ob eine Methode mit einem bestimmten Namen vorhanden ist, daher habe ich dafür eine Schnittstelle verwendet
Außerdem können Schnittstellen mehr als nur Methoden enthalten:
Von: Schnittstellen (C # -Programmierhandbuch)
Elegant und keine Notwendigkeit, Ausnahmen abzufangen oder mit Reflexion zu spielen ...
quelle
Ich weiß , das wirklich alte Post, aber hier ist eine einfache Lösung für die Arbeit mit
dynamic
Artc#
.quelle
Als
ExpandoObject
erbt das könnenIDictionary<string, object>
Sie die folgende Prüfung verwendenSie können eine Dienstprogrammmethode erstellen, um diese Prüfung durchzuführen, die den Code viel sauberer und wiederverwendbarer macht
quelle
Hier ist der andere Weg:
quelle
dynamic
.dynamic
Schlüsselwort ist viel weiter gefasst. Gehen Sie überprüfen , ob Sie testen können ,Count
indynamic foo = new List<int>{ 1,2,3,4 }
wie diese