Динамические свойства для экземпляров объекта? - PullRequest
1 голос
/ 01 февраля 2009

После предыдущего вопроса «Каковы важные правила в проектировании объектной модели», теперь я хочу задать следующий вопрос:

Есть ли способ иметь динамические свойства для экземпляров классов?

Предположим, что у нас есть объектная модель схемы:

object model

Таким образом, каждый объект может иметь множество свойств благодаря набору реализованных интерфейсов, а затем стать относительно тяжелым объектом. Создание всех возможных (и, конечно, разумных) объектов может быть способом решения этой проблемы (т.е. Pipe_Designed v.s. Pipe_Designed_NeedInspection) , но у меня есть большое количество интерфейсов, которые затрудняют это. Интересно, есть ли способ иметь динамические свойства, например, следующий диалог, позволяющий конечному пользователю выбирать доступные функции для своего нового объекта.

dialog

Ответы [ 3 ]

2 голосов
/ 01 февраля 2009

То, что вы хотите, это Properties pattern. Проверьте длинную и скучную, но умную статью от Стива Йегге об этом

1 голос
/ 01 февраля 2009

Я думаю, что, возможно, вы помещаете слишком много ролей в классы "Дорога" и "Труба", потому что ваша потребность в динамических свойствах, кажется, проистекает из различных состояний / фаз артефактов в вашей модели. Я хотел бы рассмотреть возможность создания явной модели с использованием ассоциаций с различными классами вместо того, чтобы помещать все в класс "Road" или "Pipe" с использованием интерфейсов.

1 голос
/ 01 февраля 2009

Если вы имеете в виду количество открытых свойств, используйте явную реализацию интерфейса.

Если вы имеете в виду поля (и пространство объектов для разреженных объектов): вы всегда можете использовать пакет свойств для реализации свойства.

Для примера на C #:

string IDesigned.ApprovedBy {
    get {return GetValue<string>("ApprovedBy");}
    set {SetValue("ApprovedBy", value);}
}

со словарем для значений:

readonly Dictionary<string, object> propValues =
    new Dictionary<string, object>();
protected T GetValue<T>(string name)
{
    object val;
    if(!propValues.TryGetValue(name, out val)) return default(T);
    return (T)val;
}
protected void SetValue<T>(string name, T value)
{
    propValues[name] = value;
}

Обратите внимание, что SetValue также будет хорошим местом для любых уведомлений - например, INotifyPropertyChanged в .NET для реализации шаблона наблюдателя. Многие другие архитектуры имеют нечто подобное. Вы можете сделать то же самое с ключами объекта (например, как работает EventHandlerList), но строковые ключи легче понять; -p

Это только тогда занимает столько места, сколько активно используются свойства.

Последний вариант заключается в инкапсуляции различных аспектов;

class Foo {
    public bool IsDesigned {get {return Design != null;}}
    public IDesigned Design {get;set;}
    // etc
}

Здесь Foo не реализует ни один из интерфейсов, но предоставляет доступ к ним как к свойствам.

...