Как я могу определить, есть ли у подкласса 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 и всем остальным, что реализует этот интерфейс.

Другие вопросы по тегам