Как я могу свободно ссылаться на модули в Prism, чтобы они могли или не могли существовать?

В этом вопросе о переполнении стека я узнал что Prism / Unity не так разделены, как я думал, например если у меня есть этот класс, который получает menuManager, вставленный в его конструктор, то я должен убедиться, что этот класс действительно где-то существует (я думал, что вы могли бы просто вытащить .dll который содержит класс, и контейнер будет обрабатывать его, например, вставив на его место нуль):

public class EmployeesPresenter
{
    public EmployeesPresenter(IMenuManager menuManager)
    {

    }
}

Но я могу с этим справиться: приложение не может работать без MenuModule (или, как было предложено, я мог бы иметь NullMenuModule, который ничего не делает, кроме как предотвращает поломку приложения).

Однако приложение, которое я создаю, будет иметь класс MenuManager в MenuModule, и каждый модуль должен будет зарегистрировать все, что он хочет иметь в меню, с помощью MenuManager. Однако я хочу иметь возможность заменить MenuModules, например. иметь InfragisticsMenuModule и TelerikMenuModule и т. д.

Однако, когда я, например, CustomersModule, чтобы использовать TelerikMenuModule, мне нужно сослаться на него. И когда я хочу использовать InfragisticsMenuModule, мне нужно сослаться на это.

Итак, как я смогу выполнить "горячую замену" TelerikMenuModule с InfragisticsMenuModule без перекомпиляции всех моих модулей с новыми ссылками, например Я хочу заменить это:

Application.exe
Customers.dll
TelerikMenuModule.dll

с этим:

Application.exe
Customers.dll
InfragisticsMenuModule.dll

и просто иметь возможность перезапустить приложение, и оно будет работать с новым InfragisticsMenuModule.dll, и не жалуется на то, что TelerikMenuModule.dll больше не существует.


person Edward Tanguay    schedule 20.07.2009    source источник


Ответы (2)


Вот тут-то и пригодятся интерфейсы. Вам понадобится что-то вроде:

public interface IMenuSystem
{
    // whatever operations need to be offered by a menu system
}

Application.exe и Customers.dll могут относиться только к этому интерфейсу. Им не разрешено знать о конкретной реализации.

Затем вы должны использовать шаги настройки (вызов Register... методов или использование файла конфигурации), чтобы указать, какой тип будет обеспечивать реализацию MenuSystem.

person Daniel Earwicker    schedule 20.07.2009
comment
@Earwicker: но как бы это реализовать, например Как мне вызвать Register, я нашел в документации Unity раздел Как: заполнить каталог модулей из файла конфигурации или каталога в WPF, над которым я буду работать. - person Edward Tanguay; 20.07.2009
comment
Это правильная техника. В вашей оболочке вы регистрируете объект в своем контейнере, который реализует IMenuSystem. Клиентские модули просто заявляют, что им нужна IMenuSystem, и ваша оболочка внедрит реализацию, которая знает об Infragistics или знает о Telerik. Вам нужно, чтобы каждый модуль ссылался только на DLL Contracts, которая просто содержит определения ваших интерфейсов. Это 100% правильный ответ. Мы делаем это в нашем собственном проекте, и он отлично работает. - person Anderson Imes; 20.07.2009

По очевидной причине здесь на ум приходит MEF, который предназначен для подобных вещей. У меня не было возможности использовать Unity, поэтому я не уверен, есть ли в нем что-то подобное (например, сканирование каталога для реализации IMenuModule), но MEF может это сделать.

Также предлагается поместить этот IMenuModule в общую сборку (отдельно от другой сборки). Я обычно называл эту штуку Something.Core.dll.

Итак, у вас могут быть: Application.exe, Customer.dll, Application.Core.dll и ваша конкретная реализация MenuModule.

Ваша конкретная реализация MenuModule будет ссылаться на сборку Application.Core, чтобы получить доступ к своему интерфейсу IMenuModule и реализовать его там.

person Jimmy Chandra    schedule 20.07.2009
comment
это имеет смысл, поэтому вы говорите: (1) создайте Application.Core.dll с помощью IMenuModule, (2) создайте InfragisticsMenuModule с MenuModule: IMenuModule и жестко ссылочным Application.Core.dll и (3) в Customers.dll сделайте жесткую ссылка на Application.Core.dll? Есть ли причина, по которой у вас вообще есть Application.Core, а не просто помещаете все свои интерфейсы в само приложение? - person Edward Tanguay; 20.07.2009
comment
Это просто по привычке :). Вы можете поместить его в само приложение, если хотите. - person Jimmy Chandra; 20.07.2009
comment
это работает до тех пор, пока мне не нужно зарегистрировать свой объект: container.RegisterType ‹IMenuManager, InfragisticsMenuManager› (new ContainerControlledLifetimeManager ());, тогда мне нужно иметь жесткую ссылку на InfragisticsModule. - person Edward Tanguay; 20.07.2009
comment
Это потому, что вы делаете это в модуле. Вы можете это сделать, но я бы не рекомендовал это делать. Вы должны сделать это функцией вашей оболочки, чтобы ваши модули не зависели друг от друга. - person Anderson Imes; 21.07.2009
comment
Я обновил один из ваших постов образцом. Проверить это. stackoverflow.com/questions/1152282/ - person Anderson Imes; 21.07.2009