Ich möchte dynamic
mit einer Zeichenfolge auf den Wert einer c # -Eigenschaft zugreifen :
dynamic d = new { value1 = "some", value2 = "random", value3 = "value" };
Wie kann ich den Wert von d.value2 ("random") erhalten, wenn ich nur "value2" als Zeichenfolge habe? In Javascript könnte ich d ["value2"] tun, um auf den Wert ("random") zuzugreifen, aber ich bin mir nicht sicher, wie ich das mit c # und Reflection machen soll. Am nächsten bin ich gekommen:
d.GetType().GetProperty("value2")
... aber ich weiß nicht, wie ich den tatsächlichen Wert daraus ziehen kann.
Wie immer vielen Dank für Ihre Hilfe!
Antworten:
Sobald Sie Ihr
PropertyInfo
(vonGetProperty
) haben, müssen SieGetValue
die Instanz aufrufen und übergeben, von der Sie den Wert erhalten möchten. In deinem Fall:quelle
'd.GetType().GetProperty("value2").GetValue(d)' threw an exception of type 'System.Reflection.TargetInvocationException' dynamic {System.Reflection.TargetInvocationException}
im Uhrenfenster ..?new {}
ein wirklich anonymer Typ mit definierten Eigenschaften erstellt wird, ist das Aufrufen von GetType / GetProperty sinnvoll. Was ist jedoch mit ExpandoObject. Wenn Sie GetType aufrufen, erhalten Sie einen Typ, der die Eigenschaften von ExpandoObject aufweist, jedoch nicht unbedingt die dynamischen Eigenschaften.Verweis auf Microsoft.CSharp hinzufügen. Funktioniert auch für dynamische Typen und private Eigenschaften und Felder.
Bearbeiten : Während dieser Ansatz funktioniert, gibt es eine fast 20-mal schnellere Methode aus der Microsoft.VisualBasic.dll- Assembly:
quelle
d
in der Frage).CallSite
Code mit dem Code verglichen haben,CallByName
haben Sie die beiden beim Zwischenspeichern derCallSite
Instanz verglichen ? Ich würde vermuten, dass die Kosten Ihrer ersten Methode fast nur die Aktivierung desBinder
undCallSite
nicht die Anrufung vonTarget()
Dynamitey ist eine Open-Source-
.net std
Bibliothek, die Sie wie dasdynamic
Schlüsselwort aufrufen können. Verwenden Sie jedoch eine Zeichenfolge für den Eigenschaftsnamen und nicht den Compiler, der dies für Sie erledigt. Am Ende entspricht dies der Reflexionsgeschwindigkeit (was bei weitem nicht so schnell ist) Dies ist jedoch auf den zusätzlichen Aufwand für das dynamische Caching zurückzuführen, bei dem der Compiler statisch zwischenspeichert.quelle
Die einfachste Methode, um sowohl a
setter
als auch agetter
für eine Eigenschaft zu erhalten, die für jeden Typ funktioniert, einschließlichdynamic
undExpandoObject
zu verwendenFastMember
, ist auch die schnellste Methode (es wird Emit verwendet).Sie können entweder eine
TypeAccessor
basierend auf einem bestimmten Typ oder eineObjectAccessor
basierend auf einer Instanz eines bestimmten Typs erhalten.Beispiel:
quelle
Wenn Sie nach einem dynamischen Objekt fragen, erhalten Sie häufig ein ExpandoObject (nicht im anonymen, aber statisch typisierten Beispiel der Frage oben, aber Sie erwähnen JavaScript und mein ausgewählter JSON-Parser JsonFx generiert ExpandoObjects).
Wenn Ihre Dynamik tatsächlich ein ExpandoObject ist, können Sie Reflexionen vermeiden, indem Sie sie in IDictionary umwandeln, wie unter http://msdn.microsoft.com/en-gb/library/system.dynamic.expandoobject.aspx beschrieben .
Sobald Sie in IDictionary umgewandelt haben, haben Sie Zugriff auf nützliche Methoden wie .Item und .ContainsKey
quelle
Int64? i = data.value; //data is ExpandoObject
würde der implizite Operator automatisch gesucht und aufgerufen. Wenn ich andererseits IDictionary verwenden müsste, um zu testen, ob das Feld "Wert" vorhanden ist, würde ich ein Objekt zurückerhalten, das nicht fehlerfrei in Int64 umgewandelt wird.GetProperty / GetValue funktioniert nicht für Json-Daten. Es wird immer eine Null-Ausnahme generiert. Sie können jedoch diesen Ansatz ausprobieren:
Serialisieren Sie Ihr Objekt mit JsonConvert:
Greifen Sie dann direkt darauf zu und werfen Sie es zurück in string:
Es kann direkt funktionieren, wenn Convert.ToString (Anfrage) ["DynamicFieldName"] angewendet wird, ich habe es jedoch nicht getestet.
quelle
new JavaScriptSerializer().Deserialize<object>(json);
, um zu den "Eigenschaften" in der von Ihnen vorgeschlagenen Weise zu gelangenGibt ein PropertyInfo-Objekt zurück.
Also dann tu es
quelle
GetValue(d)
muss das seinGetValue(d,null)
Auf diese Weise habe ich den Wert eines Eigenschaftswerts einer Dinamic erhalten:
quelle
Versuchen Sie
.GetType()
Folgendesnull
, um Eigenschaften aus dem dynamischen Dokument bei der Rückgabe abzurufen:quelle
In .Net Core 3.1 können Sie dies versuchen
quelle
Ähnlich wie bei der akzeptierten Antwort können Sie auch versuchen,
GetField
anstattGetProperty
.d.GetType().GetField("value2").GetValue(d);
Abhängig davon, wie das tatsächliche
Type
implementiert wurde, kann dies funktionieren, wenn GetProperty () dies nicht tut und sogar schneller sein kann.quelle