Тесная связь со связанными классами?

У меня есть специальная система волшебников, которая пока что мне вполне подходит. Для большинства мастеров страницы могут быть построены довольно общим способом, поэтому только один класс реализует эти типы страниц. Однако некоторые из них должны быть разработаны специально, поэтому для таких страниц существует абстрактный базовый класс. Из-за некоторых недостатков конструктора VS страница может ' t сам по себе является элементом управления пользовательского интерфейса, а также является абстрактным классом с общими параметрами (они существуют для свободного программирования). Итак, один из вариантов, которым я следовал, - реализовать страницу в двух классах: один для пользовательского интерфейса (который является производным от UserControl и может быть разработан), а другой - для страницы. Страница содержит экземпляр элемента управления пользовательского интерфейса и встраивает его в себя для отображения. Не оптимально, но работает.

Теперь проблема возникает из-за этой настройки: существует тесная связь между классом управления UI и классом страницы. Обычно это не было бы такой большой проблемой, за исключением того, что страницы могут быть получены из для создания специализированных версий страниц. Таким образом, производные классы управления и страницы также тесно связаны сами с собой . Итак, когда у меня есть переменные-члены, свойства и методы в классах элемента управления и страницы, которые типизированы для класса элемента управления или страницы, соответственно (т. е. класс элемента управления будет иметь свойство Page , которое указывает на страницу, в которую встроен элемент управления), мы столкнуться с большой проблемой с производными классами. Каждый производный класс должен каким-то образом изменять тип этих членов. Я думал о том, чтобы включить параметр универсального типа, который позволил бы этим членам быть универсально типизированными:

public class BaseControl<TControl, TPage>
    where TPage : BasePage<TPage, TControl>
    where TControl : BaseControl<TControl, TPage> {
    public TPage Page { get { ... } set { ... } }
    ...
}

public class BasePage<TPage, TControl>
    where TPage : BasePage<TPage, TControl>
    where TControl : BaseControl<TControl, TPage> {
    public TControl Control { get { ... } set { ... }
    ...
}

public class DerivedControl<TControl, TPage> : BaseControl<TControl, TPage>
    where TControl : DerivedControl<TControl, TPage>
    where TPage : DerivedPage<TPage, TControl> { }

public class DerivedPage<TPage, TControl> : BasePage<TPage, TControl>
    where TControl : DerivedControl<TControl, TPage>
    where TPage : DerivedPage<TPage, TControl> { }

Очевидно, это тот мусор в стиле C ++, которого я бы хотел избежать. Помимо уродства, это создает актуальную проблему, заключающуюся в том, что нужно создавать запечатанные «листовые» классы, чтобы обойти проблему бесконечной рекурсии, которую приносит нам CRTP.

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

Как такой, я немного не понимаю, как это сделать разумно. Все, что я думал до сих пор, можно заставить работать, но запах кода ужасен. Что-то мне не хватает, какой-то способ сделать это, до сих пор ускользавший от меня?

5
задан siride 12 December 2010 в 06:49
поделиться