Дочерний контейнерный модуль MEF не инициализируется - PullRequest
2 голосов
/ 29 сентября 2011

У меня есть простая иерархия контейнеров с родительским контейнером, который определен в Shell MEFBootstrapper с использованием каталога Directory, и дочерние контейнеры, которые создаются из родительского с отдельным каталогом.

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

Однако метод Initialize () для модулей, расположенных в дочерних контейнерах, никогда не вызывается.

Моя цель - использовать дочерние контейнеры в качестве конструкций сеансов, позволяя пользователю создавать новые сеансы и переключаться между ними. Но если я не могу заставить составные модули инициализировать (и разместить их представления в регионах), я как бы застрял.

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

я. Почему при инициализации не вызывается вызов модулей, загруженных в дочерний контейнер II. Как я могу «инициировать» инициализацию из экземпляра контейнера (вне контекста модуля?) Можете ли вы перебрать сборки в контейнере и вызвать инициализацию таким образом ???

[из MefBootstrapper в проекте оболочки]

    protected override DependencyObject CreateShell()
    {
        ExportProvider ep = this.Container as ExportProvider;
        this.Container.ComposeExportedValue(ep);

[из службы, управляющей моими сеансами (контейнерами)]

    [ImportingConstructor]
    public SessionService(ExportProvider provider)
    {

[конструктор для новых сессий (контейнеров)]

    private void Init(ComposablePartCatalog catalog, ExportProvider provider, string name, int callId, bool useContextProxy)
    {
        this._Name = name;
        this._CallID = callId;
        this.startTime = DateTime.Now;
        this.appHost = new CompositionContainer(catalog, new ExportProvider[] { provider });
    }

=====

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

namespace Module1
{
//, InitializationMode = InitializationMode.OnDemand
[ModuleExport("Module1.ModuleInit", typeof(Module1.ModuleInit))]
public class ModuleInit : IModule
{
    private readonly IRegionManager _regionManager;
    public IServiceLocator _serviceLocator;

    [ImportingConstructor]
    public ModuleInit(IRegionManager regionManager, IServiceLocator serviceLocator)
    {
        _regionManager = regionManager;
        _serviceLocator = serviceLocator;
    }

    #region IModule Members


    public void Initialize()
    {
        // Use View Discovery to automatically display the MasterView when the TopLeft region is displayed.
        _regionManager.RegisterViewWithRegion(RegionNames.TopLeftRegion, () => _serviceLocator.GetInstance<MasterView>());
    }

    #endregion
}

}

Ответы [ 3 ]

3 голосов
/ 30 сентября 2011

Я скачал твой код и посмотрел его.Я сразу нашел проблему.Загрузчик фактически получает экспорт благодаря каталогу каталогов, подобному следующему:

DirectoryCatalog catalog = new DirectoryCatalog(".");
this.AggregateCatalog.Catalogs.Add(catalog);

Это означает, что вы получите экспорт из сборок в этом каталоге.Таким образом, вам просто нужно скопировать все сборки с экспортируемыми типами в каталог «.», То есть исполняющий каталог (Debug / bin).

Просто скопируйте Module1 и Module2 в каталог bin ичто-нибудь будет изящно скомпоновано:)

На самом деле я обнаружил, что события после сборки, которые должны были копировать модули в каталоге bin, не работали.Может быть, потому что вы переименовали что-то.Поэтому, если вы хотите, чтобы он автоматически копировал сборки после сборки, просто замените фактическое событие после сборки на это:

copy "$(TargetDir)\$(TargetFileName)" "$(TargetDir)\..\..\..\Shell\bin\$(ConfigurationName)\"
1 голос
/ 29 сентября 2011

У меня уже была эта проблема много раз, и ее решение действительно просто.

Удалите конструктор из вашего модуля.Модули Prism активируются не так, как для классических экспортируемых типов, поэтому модули не могут использовать ImportingConstructor для импорта необходимых вам сервисов.Вместо этого инициализируйте их с помощью ServiceLocator в методе Initialize.

Это будет работать:

[ModuleExport("Module1.ModuleInit", typeof(Module1.ModuleInit))]
public class ModuleInit : IModule
{
    private readonly IRegionManager _regionManager;

    public void Initialize()
    {
        _regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();

        _regionManager.RegisterViewWithRegion(RegionNames.TopLeftRegion, () => _serviceLocator.GetInstance<MasterView>());
    }
}

Я также думаю, что это поведение вызывает беспокойство.

0 голосов
/ 05 сентября 2012

У меня была такая же проблема, когда мой метод Initialize () модулей не вызывался ... Я понял, что у меня опущено ключевое слово "override" в моем методе Initialize, который был объявлен виртуальным в базовом классе Module, что все мои модули наследуются от ... добавлено "переопределение", и это сработало!

...