Moja sytuacja jest bardzo prosta. Gdzieś w moim kodzie mam to:
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
//How to do this?
if (myVariable.MyProperty.Exists)
//Do stuff
Zasadniczo moje pytanie brzmi: jak sprawdzić (bez zgłaszania wyjątku), czy pewna właściwość jest dostępna w mojej zmiennej dynamicznej. Mógłbym to zrobić, GetType()
ale wolałbym tego uniknąć, ponieważ tak naprawdę nie muszę znać typu obiektu. Wszystko, co naprawdę chcę wiedzieć, to czy właściwość (lub metoda, jeśli to ułatwia życie) jest dostępna. Jakieś wskazówki?
c#
dynamic
dynamic-keyword
zaokrąglenie
źródło
źródło
Odpowiedzi:
Myślę, że nie ma sposobu, aby dowiedzieć się, czy
dynamic
zmienna ma określony element członkowski bez próby uzyskania do niego dostępu, chyba że ponownie zaimplementowano sposób obsługi powiązania dynamicznego w kompilatorze C #. Który prawdopodobnie zawiera wiele zgadywania, ponieważ jest on zdefiniowany w implementacji, zgodnie ze specyfikacją C #.Więc powinieneś spróbować uzyskać dostęp do członka i złapać wyjątek, jeśli się nie powiedzie:
źródło
IDictionary
i pracę z tym, działa to tylko naExpandoObject
, nie będzie działać na żadnym innymdynamic
obiekcie.RuntimeBinderException
jest wMicrosoft.CSharp.RuntimeBinder
przestrzeni nazw.Myślałem, że zrobię porównanie odpowiedzi Martijna i Svicka ...
Następujący program zwraca następujące wyniki:
W rezultacie sugeruję użycie odbicia.Patrz poniżej.W odpowiedzi na komentarz Bland:
Wskaźniki to
reflection:exception
tiki dla 100 000 iteracji:... dość uczciwie - jeśli spodziewasz się, że zawiedzie z prawdopodobieństwem mniejszym niż ~ 1/47, to idź na wyjątek.
Powyższe zakłada, że biegasz za
GetProperties()
każdym razem. Możesz przyspieszyć ten proces, buforując wynikiGetProperties()
dla każdego typu w słowniku lub podobnym. Może to pomóc, jeśli ciągle sprawdzasz ten sam zestaw typów.źródło
IIDynamicMetaObjectProvider
. Rozumiem motywację twojej odpowiedzi i doceniam ją. Odpowiedź jest sprawiedliwa.Może użyć refleksji?
źródło
Where
.Any(p => p.Name.Equals("PropertyName"))
((Type)myVar.GetType()).GetProperties().Any(x => x.Name.Equals("PropertyName"))
. Rzutowanie na typ jest wymagane, aby kompilator był zadowolony z lambda.Na wszelki wypadek pomaga komuś:
Jeśli metoda
GetDataThatLooksVerySimilarButNotTheSame()
zwróciExpandoObject
, możesz także rzutować naIDictionary
przed sprawdzeniem.źródło
Dwa typowe rozwiązania tego problemu obejmują nawiązywanie połączenia i łapanie go
RuntimeBinderException
, używanie refleksji do sprawdzania połączenia lub szeregowanie do formatu tekstowego i analizowanie stamtąd. Problem z wyjątkami polega na tym, że są one bardzo wolne, ponieważ gdy jeden jest konstruowany, aktualny stos wywołań jest szeregowany. Serializacja do JSON lub coś analogicznego wiąże się z podobną karą. To pozostawia nam refleksję, ale działa tylko wtedy, gdy obiekt leżący pod spodem jest w rzeczywistości POCO z prawdziwymi elementami. Jeśli jest to dynamiczne opakowanie wokół słownika, obiektu COM lub zewnętrznej usługi internetowej, odbicie nie pomoże.Innym rozwiązaniem jest użycie
DynamicMetaObject
nazw, aby uzyskać nazwy członków, tak jak je widzi DLR. W poniższym przykładzie używam klasy statycznej (Dynamic
) do testowaniaAge
pola i wyświetlenia go.źródło
Dynamitey
pakiet nuget już to robi. ( nuget.org/packages/Dynamitey )Odpowiedź Denisa skłoniła mnie do zastanowienia się nad innym rozwiązaniem wykorzystującym JsonObjects,
moduł sprawdzania właściwości nagłówka:
a może lepiej:
na przykład:
źródło
Cóż, napotkałem podobny problem, ale w testach jednostkowych.
Za pomocą SharpTestsEx możesz sprawdzić, czy istnieje właściwość. Używam tego do testowania moich kontrolerów, ponieważ ponieważ obiekt JSON jest dynamiczny, ktoś może zmienić nazwę i zapomnieć o zmianie w javascript lub coś takiego, więc testowanie wszystkich właściwości podczas pisania kontrolera powinno zwiększyć moje bezpieczeństwo.
Przykład:
Teraz, używając SharTestsEx:
Korzystając z tego, testuję wszystkie istniejące właściwości za pomocą „Should (). NotThrow ()”.
Prawdopodobnie nie jest to temat, ale może być przydatne dla kogoś.
źródło
((string)(testedObject.MyName)).Should().Be("I am a testing object");
Zgodnie z odpowiedzią @karask, możesz zawinąć funkcję jako pomocnik w ten sposób:
źródło
Dla mnie to działa:
źródło
null
nie oznacza, że właściwość nie istniejeJeśli kontrolujesz typ używany jako dynamiczny, czy nie możesz zwrócić krotki zamiast wartości dla każdego dostępu do właściwości? Coś jak...
Być może jest to naiwna implementacja, ale jeśli za każdym razem zbudujesz jedną z nich wewnętrznie i zwrócisz ją zamiast rzeczywistej wartości, możesz sprawdzić
Exists
dostęp do każdej właściwości, a następnie nacisnąć,Value
jeśli ma wartość byciadefault(T)
(i nieistotną), jeśli tak nie jest.To powiedziawszy, być może brakuje mi pewnej wiedzy o tym, jak działa dynamika, i może to nie być praktyczną sugestią.
źródło
W moim przypadku musiałem sprawdzić, czy istnieje metoda o określonej nazwie, więc użyłem do tego interfejsu
Interfejsy mogą zawierać nie tylko metody:
Z: Interfaces (C # Programming Guide)
Elegancki i nie musisz wychwytywać wyjątków ani bawić się refleksją ...
źródło
Wiem, że to bardzo stary post, ale tutaj jest to proste rozwiązanie do pracy z
dynamic
typu wc#
.źródło
Jak
ExpandoObject
dziedziczyIDictionary<string, object>
, możesz użyć następującego sprawdzeniaMożesz wykonać metodę narzędziową do wykonania tej kontroli, która sprawi, że kod będzie znacznie czystszy i będzie można go ponownie użyć
źródło
Oto inny sposób:
źródło
dynamic
.dynamic
słowo kluczowe jest znacznie szerszym tematem. Sprawdź, czy możesz sprawdzićCount
wdynamic foo = new List<int>{ 1,2,3,4 }
ten sposób