После нескольких часов чтения статей и форумов, связанных с Prism, я наткнулся на статью «Как создать приложение в стиле Outlook» в блоге Эрвина ван дер Валька - Как создать приложение в стиле Outlook .
В одной части архитектуры для разрешения экземпляров типов использовался дочерний контейнер Unity. Это именно то, что мне было нужно для ответа на мой 2-й вопрос: мне нужно было сделать инъекцию зависимостей "scoped" (по окнам) (например, EventAggregator, управление областью окна и т. Д.)
Вот как я создаю новое окно:
private IShellWindow CreateNewShell(IRegionManager regionManager)
{
IUnityContainer childContainer = this.Container.CreateChildContainer();
... register types in child container ...
var window = new ShellWindow();
RegionManager.SetRegionManager(window, regionManager);
window.Content = childContainer.Resolve<MapDocumentView>();
return window;
}
Таким образом, MapDocumentView и все его компоненты будут внедрены (при необходимости) в экземпляры области окна.
Теперь, когда у меня есть возможности для ввода объектов с областью видимости, я могу получить карту с областью окна в моем модуле MapPresenter. Чтобы ответить на мой первый вопрос, я определил интерфейс IHostApplication, который реализуется Bootstrapper, у которого есть свойство MapPresenterRegistry. Этот интерфейс добавлен в основной контейнер.
После инициализации модули зарегистрируют своих презентаторов, а при создании окна они будут созданы.
Итак, для инициализации модуля:
public void Initialize()
{
...
this.hostApplication.MapPresenterRegistry.Add(typeof(ModuleSpecificMapPresenter));
...
}
Код, который инициализирует окно карты:
private void View_Loaded(object sender, RoutedEventArgs e)
{
// Register map in the == scoped container ==
container.RegisterInstance<IMap>(this.View.Map);
// Create map presenters
var hostApplication = this.container.Resolve<IHostApplication>();
foreach (var mapPresenterType in hostApplication.MapPresenterRegistry)
{
var mapPresenter = this.container.Resolve(mapPresenterType) as IMapPresenter;
if (mapPresenter != null)
{
this.mapPresenters.Add(mapPresenter);
}
}
}
MapPresenter для конкретного модуля:
public ModuleSpecificMapPresenter(IEventAggregator eventAggregator, IMap map)
{
this.eventAggregator = eventAggregator;
this.map = map;
this.eventAggregator.GetEvent<AWindowSpecificEvent>().Subscribe(this.WindowSpecificEventFired);
// Do stuff on with the map
}
Так вот в чем суть моего решения. Что мне действительно не нравится, так это то, что я не использую управление регионами таким образом. У меня в значительной степени есть собственный код для работы.
Если у вас есть какие-либо дальнейшие мысли, я был бы рад выслушать их.
Эдуард