Как я могу использовать макет элемента управления в веб-проекте, и чтобы компилятор не жаловался на это? - PullRequest
1 голос
/ 22 октября 2010

У нас есть пара мини-приложений (один материал для поиска в веб-формах), которые должны запускаться в контексте гораздо более крупного сайта и приложения (далее - «Монолит»)

Мы не хотим устанавливать Monolith на машину каждого разработчика, поэтому мы хотим, чтобы некоторые разработчики могли разрабатывать эти небольшие приложения в своем собственном изолированном проекте с песочницей (далее «Песочница»). Идея состоит в том, что мы переместим (1) полученную DLL и (2) файл веб-формы (aspx) из песочницы в монолитное веб-приложение, где оно будет работать.

Это все хорошо, за исключением того, что пара этих маленьких приложений должна использовать элемент управления, который существует в Monolith. И этот контроль не будет работать без всей инфраструктуры Монолита за ним.

Итак, у нас была прекрасная идея создать макет контроля. Мы удалили элемент управления с тем же пространством имен, именем класса и свойствами, что и элемент управления в Monolith. Мы скомпилировали это в DLL и поместили в Песочницу. Мы можем развиваться против этого, и он просто выплевывает данные типа Lorem Ipsum, что круто.

Единственная ссылка на элемент управления:

<Namespace:MyControl runat="server"/>

В Песочнице это вызывает фиктивный объект. В Монолите это вызывает фактический контроль. Мы поняли, что, поскольку единственное соединение с элементом управления - это тег выше, он должен работать с обеих сторон. Во время выполнения он просто вызывает разные вещи, в зависимости от того, где он запущен.

Итак, мы переместили файл aspx и DLL приложения (, а не DLL фиктивного объекта) в Monolith ... и он не запустился.

Кажется, мы не рассчитывали на файл "mypage.aspx.designer.cs", выходящий из Visual Studio. Это скомпилировано в DLL, и оно имеет ссылку на нашу библиотеку фиктивных объектов. Поэтому, когда он работает в Monolith, он жалуется, что не может загрузить библиотеку фиктивного объекта.

Итак, наша цель состоит в том, чтобы иметь тег управления, как указано выше, и вызывать разные вещи в зависимости от среды. В обоих случаях он будет выполнять одно и то же пространство имен и класс, но это пространство имен и класс будут разными в двух средах . В Монолите это был бы наш фактический контроль. В Песочнице это будет наш фиктивный объект.

По сути, мы хотим, чтобы этот тег оценивался во время выполнения, а не во время компиляции. Мы хотим, чтобы в DLL не было никаких ссылок на DLL фиктивного объекта.

возможно? Другие решения для основной проблемы?

Решение

В конце концов, это было довольно просто.

Я работаю над своим приложением с элементом управления, который скомпилирован с моей библиотекой фиктивного объекта. Когда я готов к компиляции в последний раз, я удаляю ссылку на библиотеку фиктивного объекта и добавляю ссылку на библиотеку Monolith DLL . Затем я компилирую и использую эту DLL.

Полученная DLL не имеет ни малейшего представления, что она не была разработана против Monolith DLL все время.

Ответы [ 2 ]

2 голосов
/ 22 октября 2010

Это похоже на работу для слабой связи!Одним из наиболее полезных, но наименее соблюдаемых принципов разработки программного обеспечения является Dependency Inversion;классы не должны напрямую зависеть от других конкретных классов, но от абстракций, таких как абстрактный базовый класс или интерфейс.

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

Я бы начал с создания интерфейса для вашего элемента управления, который определяет функциональные возможности, доступные для потребителей элемента управления (методы, свойства и т. д.).Пусть оба элемента управления Monolith и mocked-контроль реализуют этот интерфейс и объявляют об использовании любого элемента управления как типа интерфейса вместо Monolith или mock.Поместите этот интерфейс в относительно легкую DLL-библиотеку, отделенную от макета объекта, Песочницы и существующих библиотек DLL Monolith, которые вы можете разместить на машинах разработчика вместе с DLL-библиотекой моделируемого объекта, а также присутствует в базе кода Monolith.Теперь классам, которым нужен ваш контроль, нужен только интерфейс;вам больше не нужны прямые ссылки на Monolith или на любую фиктивную DLL.

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

Итак, определите третий класс, который знает, как подключить элемент управления к классам, которые зависят от него.Метод перехода состоит в том, чтобы ввести инфраструктуру IoC, которая действует как большая фабрика для любого объекта, который либо является зависимостью, либо имеет зависимость.Вы регистрируете один из двух элементов управления в качестве реализации интерфейса для конкретной среды (макет для блоков разработки, элемент управления Monolith в производстве);регистрационная информация специфична для каждой среды (обычно находится в app.config).Затем вместо обновления экземпляра класса элемента управления вы просите контейнер предоставить вам экземпляр класса, который реализует интерфейс, и из него появляется новый макет или элемент управления Monolith.Или поместите элемент управления и все зависимые классы в контейнер IoC и запросите зависимые классы, которые контейнер вернет полностью «гидратированными» со ссылкой на их элемент управления.Все это происходит без каких-либо классов, которые зависят от элемента управления, который должен знать, откуда он появился, или даже точно, что это такое.

Платформы IoC могут быть болезненными для интеграции в существующий дизайн.Практически можно создать класс Factory, который использует отражение для динамического создания экземпляра любого из двух элементов управления, и поместить AppSetting в файл app.config, который сообщит фабрике, какую сборку и тип использовать в этой среде.Затем, где бы вы обычно не создавали новый элемент управления, вместо этого вызывайте Factory.

0 голосов
/ 22 октября 2010

У меня нет супербыстрого решения для вас (возможно, кто-то другой), но вас может заинтересовать контейнер IoC, такой как Unity .

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