Chciałbym uzyskać dostęp do wartości właściwości dynamic
C # za pomocą ciągu:
dynamic d = new { value1 = "some", value2 = "random", value3 = "value" };
Jak mogę uzyskać wartość d.value2 („losowa”), jeśli mam tylko „wartość2” jako ciąg? W javascript mógłbym zrobić d ["value2"], aby uzyskać dostęp do wartości ("random"), ale nie jestem pewien, jak to zrobić za pomocą C # i odbicia. Najbliższe, do których doszedłem, to:
d.GetType().GetProperty("value2")
... ale nie wiem, jak uzyskać z tego rzeczywistą wartość.
Jak zawsze dziękujemy za pomoc!
Odpowiedzi:
Gdy już masz swój
PropertyInfo
(fromGetProperty
), musisz zadzwonićGetValue
i przekazać instancję, z której chcesz uzyskać wartość. W Twoim przypadku:źródło
'd.GetType().GetProperty("value2").GetValue(d)' threw an exception of type 'System.Reflection.TargetInvocationException' dynamic {System.Reflection.TargetInvocationException}
w oknie zegarka z tym ..?new {}
tworzy prawdziwy anonimowy typ ze zdefiniowanymi właściwościami, wywołanie GetType / GetProperty ma sens, ale co z ExpandoObject, który, jeśli wywołasz GetType, otrzymasz typ, który ma właściwości ExpandoObject, ale niekoniecznie jego właściwości dynamiczne.Dodaj odniesienie do Microsoft.CSharp. Działa również w przypadku typów dynamicznych oraz prywatnych nieruchomości i pól.
Edycja : Chociaż to podejście działa, istnieje prawie 20 razy szybsza metoda z zestawu Microsoft.VisualBasic.dll :
źródło
d
w pytaniu).CallSite
kod zCallByName
kodem, czy porównałeś te dwa podczas buforowaniaCallSite
instancji? Podejrzewam, koszt pierwszej metody jest prawie czysto aktywizacjaBinder
iCallSite
nie wzywanieTarget()
Dynamitey to
.net std
biblioteka open source , która pozwala nazywać ją jakdynamic
słowo kluczowe, ale używając ciągu znaków dla nazwy właściwości zamiast kompilatora, który robi to za Ciebie, i kończy się na tym, że jest równa szybkości odbicia (co nie jest tak szybkie jak przy użyciu dynamicznego słowa kluczowego, ale jest to spowodowane dodatkowym obciążeniem buforowania dynamicznego, gdy kompilator buforuje statycznie).źródło
Najłatwiejszą metodą uzyskania zarówno a, jak
setter
i agetter
dla właściwości, która działa dla dowolnego typu, w tymdynamic
iExpandoObject
jest użycieFastMember
najszybszej metody (wykorzystuje Emit).Możesz uzyskać wynik
TypeAccessor
oparty na danym typie lub naObjectAccessor
podstawie wystąpienia określonego typu.Przykład:
źródło
W większości przypadków, gdy pytasz o obiekt dynamiczny, otrzymujesz ExpandoObject (nie w powyższym przykładzie anonimowym, ale statycznym, ale wspominasz o JavaScript, a mój wybrany parser JSON JsonFx generuje ExpandoObjects).
Jeśli twoja dynamika jest w rzeczywistości ExpandoObject, możesz uniknąć odbicia, przesyłając ją do IDictionary, jak opisano na http://msdn.microsoft.com/en-gb/library/system.dynamic.expandoobject.aspx .
Po przesłaniu do IDictionary masz dostęp do przydatnych metod, takich jak .Item i .ContainsKey
źródło
Int64? i = data.value; //data is ExpandoObject
automatycznie wyszukałbym i wywołał niejawny operator. Z drugiej strony, gdybym musiał użyć IDictionary do sprawdzenia, czy istnieje pole „value”, dostałbym z powrotem obiekt, który nie będzie rzutowany bez błędu na Int64 ?.GetProperty / GetValue nie działa dla danych Json, zawsze generuje wyjątek zerowy, jednak możesz wypróbować następujące podejście:
Serializuj swój obiekt przy użyciu JsonConvert:
Następnie uzyskaj do niego bezpośredni dostęp, przesyłając go z powrotem na łańcuch:
Może działać bezpośrednio, stosując Convert.ToString (request) ["DynamicFieldName"], jednak nie testowałem.
źródło
new JavaScriptSerializer().Deserialize<object>(json);
aby dostać się do „nieruchomości” w sposób, który sugerowałeśzwraca obiekt PropertyInfo.
Więc zrób
źródło
GetValue(d)
musi byćGetValue(d,null)
Oto sposób, w jaki otrzymałem wartość właściwości dinamic:
źródło
Aby uzyskać właściwości z dokumentu dynamicznego po
.GetType()
zwróceniunull
, spróbuj tego:źródło
W .Net core 3.1 możesz spróbować w ten sposób
źródło
Podobnie jak w przypadku zaakceptowanej odpowiedzi, możesz również spróbować
GetField
zamiastGetProperty
.d.GetType().GetField("value2").GetValue(d);
W zależności od tego, jak rzeczywistość
Type
została zaimplementowana, może to działać, gdy GetProperty () nie działa, a nawet może być szybsze.źródło