Моя ситуация очень проста. Где-то в моем коде у меня есть это:
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
//How to do this?
if (myVariable.MyProperty.Exists)
//Do stuff
Итак, в основном мой вопрос заключается в том, как проверить (без исключения), что определенное свойство доступно для моей динамической переменной. Я мог бы сделать, GetType()
но я бы предпочел избежать этого, так как мне не нужно знать тип объекта. Все, что я действительно хочу знать, это доступность свойства (или метода, если это облегчает жизнь). Есть указатели?
c#
dynamic
dynamic-keyword
roundcrisis
источник
источник
Ответы:
Я думаю, что нет способа выяснить, есть ли у
dynamic
переменной определенный член, не пытаясь получить к нему доступ, если только вы повторно не реализовали способ динамического связывания, обрабатываемый в компиляторе C #. Который, вероятно, будет включать много догадок, потому что это определяется реализацией в соответствии со спецификацией C #.Таким образом, вы должны попытаться получить доступ к члену и поймать исключение, если оно завершится неудачно:
источник
IDictionary
и работу с этим, который работает только над нимExpandoObject
, он не будет работать ни с каким другимdynamic
объектом.RuntimeBinderException
находится вMicrosoft.CSharp.RuntimeBinder
пространстве имен.Я думал , что я хотел бы сделать сравнение ответа Мартейн в и ответ svick в ...
Следующая программа возвращает следующие результаты:
В результате я бы предложил использовать рефлексию.Увидеть ниже.Отвечая на мягкий комментарий:
Коэффициенты - это
reflection:exception
тики для 100000 итераций:... достаточно справедливо - если вы ожидаете, что он потерпит неудачу с вероятностью менее ~ 1/47, тогда сделайте исключение.
Выше предполагается, что вы работаете
GetProperties()
каждый раз. Вы можете ускорить процесс, кэшируя результатGetProperties()
для каждого типа в словаре или подобном. Это может помочь, если вы снова и снова проверяете один и тот же набор типов.источник
IIDynamicMetaObjectProvider
. Я понимаю мотивацию вашего ответа и ценю это. Справедливо ответить так.Может быть, использовать отражение?
источник
Where
:.Any(p => p.Name.Equals("PropertyName"))
((Type)myVar.GetType()).GetProperties().Any(x => x.Name.Equals("PropertyName"))
. Приведение к типу требуется, чтобы компилятор радовался лямбде.На всякий случай это кому-то поможет:
Если метод
GetDataThatLooksVerySimilarButNotTheSame()
возвращает,ExpandoObject
вы также можете привести кIDictionary
перед проверкой.источник
Два распространенных решения этого включают в себя выполнение вызова и перехват
RuntimeBinderException
, использование отражения для проверки вызова или сериализацию в текстовый формат и разбор оттуда. Проблема с исключениями заключается в том, что они очень медленные, потому что при их создании текущий стек вызовов сериализуется. Сериализация в JSON или что-то аналогичное влечет за собой аналогичное наказание. Это оставляет нам отражение, но работает только в том случае, если базовый объект на самом деле является POCO с реальными членами. Если это динамическая оболочка вокруг словаря, COM-объекта или внешнего веб-сервиса, то рефлексия не поможет.Другое решение состоит в том, чтобы использовать
DynamicMetaObject
для получения имен членов так, как их видит DLR. В приведенном ниже примере я использую статический класс (Dynamic
) для проверкиAge
поля и его отображения.источник
Dynamitey
пакет nuget уже делает это. ( nuget.org/packages/Dynamitey )Ответ Дениса заставил меня подумать о другом решении, используя JsonObjects,
средство проверки свойств заголовка:
а может лучше:
например:
источник
Ну, я столкнулся с подобной проблемой, но на модульных тестах.
Используя SharpTestsEx, вы можете проверить, существует ли свойство. Я использую это тестирование своих контроллеров, потому что, поскольку объект JSON является динамическим, кто-то может изменить имя и забыть изменить его в javascript или что-то в этом роде, поэтому тестирование всех свойств при написании контроллера должно повысить мою безопасность.
Пример:
Теперь, используя SharTestsEx:
Используя это, я тестирую все существующие свойства, используя «Should (). NotThrow ()».
Это, вероятно, не по теме, но может быть полезно для кого-то.
источник
((string)(testedObject.MyName)).Should().Be("I am a testing object");
Исходя из ответа @karask, вы можете обернуть функцию как помощник так:
источник
Для меня это работает:
источник
null
не означает, что собственность не существуетЕсли вы контролируете тип, используемый как динамический, не могли бы вы вернуть кортеж вместо значения для каждого доступа к свойству? Что-то вроде...
Возможно, это наивная реализация, но если вы каждый раз создаете один из них внутренне и возвращаете его вместо фактического значения, вы можете проверять
Exists
каждый доступ к свойству, а затем нажимать,Value
если это происходит со значениемdefault(T)
(и не имеет значения), если это не так.Тем не менее, я мог бы упустить некоторые знания о том, как работает динамический, и это не может быть реальным предложением.
источник
В моем случае мне нужно было проверить существование метода с определенным именем, поэтому я использовал для этого интерфейс
Кроме того, интерфейсы могут содержать больше, чем просто методы:
From: Interfaces (Руководство по программированию в C #)
Элегантный и не нужно ловить исключения или играть с отражением ...
источник
Я знаю, что это действительно старый пост, но здесь есть простое решение для работы с
dynamic
вводомc#
.источник
Как
ExpandoObject
наследует,IDictionary<string, object>
вы можете использовать следующую проверкуВы можете сделать служебный метод для выполнения этой проверки, который сделает код намного чище и может использоваться повторно
источник
Вот другой способ:
источник
dynamic
.dynamic
Ключевое слово гораздо шире. Пойди проверь, можешь ли ты проверитьCount
вdynamic foo = new List<int>{ 1,2,3,4 }
таком виде