Как управлять (или устранять) параллельными иерархиями классов? - PullRequest
5 голосов
/ 05 марта 2011

Я проектирую простой механизм создания форм, в котором пользователи могут создавать новые формы, используя различные типовые поля полей (Date, Text, DropDown)

Я решил смоделировать объект домена (поле формы) независимо от объектов, которые будут использоваться для визуализации этих полей в пользовательском интерфейсе.

Вот интерфейс, который определяет контракт для домена и некоторые его специализации:

namespace Acme.Core.Domain{
    public interface IFormField
            {
                bool Visible { get; set; }
                string Key { get; set; }
                event EventHandler<FieldVisibilityChangedEventArgs> VisibilityChanged;
                FieldType Type{get;}
                void Validate(IEnumerable<ValidationError> errors);
                int DataId {get;set;}
            }

    public interface IDropDownField:IFormField{

                IDictionary<string, string> Items { get; set; }
                KeyValuePair<string, string> SelectedValue { get; set; }

        }
     public interface IDateField:IFormField{

                DateTime? SelectedDate{get;set}

        }
}

Для пользовательского интерфейса я построил иерархию параллельных типов. Это сохраняет объект домена, который связан с бизнес-правилами вокруг проверки данных, отдельно от вопросов пользовательского интерфейса, а именно, как визуализировать данное поле (MVC HtmlHelper против WebForm WebControl):

namespace Acme.UI{

        public interface IControl 
        {
                //parallel to IFormField
                bool Visible { get; set; }
                string ID { get; set; }     
        }

        public interface IDropListControl:IControl 
        {
                //parallel to IDropDownField

        }
        public interface IDatePickerControl: IControl 
        {
                //parallel to IDateField

        }

       public interface IControlFactory {

             IControl CreateControl(IFormField field);
       }
    }

Хотя этот дизайн дает мне свободу в разработке модели предметной области независимо от пользовательского интерфейса, я не нашел чистого способа соединения и управления двумя иерархиями. Я чувствую, что должен иметь возможность использовать универсальные шаблоны для соединения параллельных классов друг с другом, но я не совсем понимаю, как это будет выглядеть. Существует ли шаблон, который решает проблему ассоциации или вообще устраняет необходимость в параллельных иерархиях классов?

РЕДАКТИРОВАТЬ: Мой уровень пользовательского интерфейса ссылается на уровень моего бизнеса (Core.csproj). Вот несколько примеров того, как я подключаю иерархию классов пользовательского интерфейса к иерархии классов домена. Эти типы в настоящее время не используют дженерики, но я чувствую, что они должны.

    // create concrete instances of IControl based on the the domain object passed in 
   public interface IControlFactory {

                 IControl CreateControl(IFormField field);
       }
       // scrape values form the UI controls and apply them to the appropriate domain object
       public interface IFormFieldDataBinder{

                void Bind(IFormField field, IControl control);
       }

1 Ответ

1 голос
/ 05 марта 2011

Я думаю, что разница между двумя иерархиями настолько мала, что вы действительно должны подумать о том, каково значение-различие.Если все, что вы рассматриваете, имеет, например, несколько элементов управления выпадающего списка, которые имеют разные формы рендеринга, то спросите себя, если не в конструкторе, где вы собираетесь выбрать конкретные элементы управления?

Возможно, ваш IDropdownListControl может быть базовым классом с абстрактным методом 'Render'?

Ваши IFormField и IControl настолько похожи, что я не вижу, что вы покупаетес обоими?

В частности, IDropDownField действительно выглядит как объект модели в терминах MVC, это данные, которые поле будет содержать при создании экземпляра формы.Дело не в том, как формируется форма (вы заявили, что это модель предметной области).

Должны ли все IDropListControls поддерживать модель IDropDownField, возможно?(в этом случае я бы просто отбросил IDropDownField и объявил бы свойства непосредственно в IDropListControl).

Рассмотрим принцип повторно использованной абстракции.Для каждого интерфейса, который вы создаете, можете ли вы представить себе две реализации или это действительно конкретные классы?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...