2009-02-01 5 views
1

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

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

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

object model

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

dialog

ответ

2

Что вы хотите Properties pattern. Проверьте длинный и скучный, но умный товар от Steve Yegge on this

1

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

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

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

+0

Дорогой Марк Ваш ответ очень полезен и специально полон, я считаю, что статья в стиле лучшая, потому что это дало мне более подробную информацию. Еще раз спасибо – AliPST

1

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

Смежные вопросы