Как я могу определить, есть ли у подкласса Expando определенное свойство?
Я создаю приложение, которое я хочу иметь расширяемый набор свойств (каждый из которых является RatingProperty). Я также хочу проверить, что любые динамические свойства имеют тип RatingProperty.
В документации Expando говорится:
Совет: Если вы хотите проверить значение динамического свойства с помощью класса Property, вы можете создать экземпляр класса Property и вызвать его метод validate() для значения.
Поэтому, если я хочу проверить динамическое свойство, мне нужно знать, что такое нединамические свойства класса. Как я могу спросить мой класс, каковы его определенные свойства?
Я рассмотрел создание метода класса, который принимает строку и возвращает true, если эта строка находится в списке имен свойств, которые я создаю и поддерживаю, но это похоже на хак. Я искал в Google советы, но мне не повезло.
Спасибо пэт
4 ответа
После небольшого исследования (черт возьми, лентяйка!) Я нашел решение, которое я считаю приемлемым:
Динамическое свойство не может иметь тип подкласса db. Таким образом, есть два различных шага, которые необходимо предпринять. Сначала вам нужно создать экземпляр вашего класса свойств и проверить ваше значение:
test = db.RatingProperty()
if test.validate(valueToSave):
#do your thing
Далее вам нужно проверить, является ли свойство, которое вы хотите сохранить, объявленным:
if valueToSaveKey not in myObject.properties():
#if not save it as desired
myObject.valueToSaveKey = valueToSave
Недостатком здесь является то, что значение, которое вы сохраняете, не сохраняется как требуемый тип свойства.
http://code.google.com/appengine/docs/python/datastore/modelclass.html
В db.Model есть методы для определения всех свойств экземпляра.
Класс предоставляет список объектов Property: db.Model.properties()
Экземпляр предоставляет только динамические имена: instance.dynamic_properties()
Вы хотите пройтись по списку, построить объекты Property и запустить p.validate().
for p_name in instance.dynamic_properties():
p = db.RatingProperty()
p.validate() # raises BadValueError, etc.
Возможно, я неправильно понимаю ваш вопрос, но если у вас есть список свойств, которые вы ожидаете найти, почему бы просто не использовать стандартную модель db.Model вместо Expando? Вы можете добавить дополнительные свойства в класс Model, если вы либо предоставите значение по умолчанию, либо не сделаете их обязательными.
Это на самом деле довольно просто!
ExpandoObject реализует (IDictionary<String, Object>)
так что вам просто нужно сделать это:
dynamic person = new ExpandoObject();
person.FirstName = "Barack";
person.LastName = "Obama"
(((IDictionary<String, Object>)person).Keys
=> { "FirstName", "LastName" }
(((IDictionary<String, Object>)person).ContainsKey("FirstName")
=> true
Примечание: вам нужно явно привести к (IDictionary<string, object>
потому что ExpandoObject явно реализует этот интерфейс - а сам экземпляр не имеет ContainsKey()
или же Keys
,
Не ожидайте, что этот метод будет работать со всеми динамическими объектами - только ExpandoObject и всем остальным, что реализует этот интерфейс.