MEF子容器模块未初始化

时间:2011-09-29 05:44:00

标签: module prism mef containers hierarchy

我有一个简单的容器层次结构,其父容器在Shell MEFBootstrapper中使用目录编目定义,子容器在父目录下创建,具有不同的目录。

我的子容器也使用DirectoryCatalog(与父路径不同的路径),我可以看到容器在运行时具有汇编和部件信息。

但是,永远不会调用位于子容器中的模块的Initialize()方法。

我的目标是将子容器用作会话构造,允许用户创建新会话并在它们之间切换。但如果我不能让组成模块初始化(并将他们的观点放入区域),我就会陷入困境。

我原本想过使用事件聚合器从会话管理器中引发一个事件,以允许模块监听事件并进行自我初始化,但这似乎也不起作用。

我。为什么没有在加载到子容器中的模块上调用Initialize II。如何从容器实例“触发”初始化(在模块上下文之外?)你可以迭代容器中的程序集并触发Initialize吗???

[来自shell项目中的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 个答案:

答案 0 :(得分:3)

我下载了你的代码并查看了它。我马上发现了这个问题。由于像这样的DirectoryCatalog,引导程序实际上正在获取导出:

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

这意味着您将从此目录中的程序集中获取导出。所以你只需要在目录“。”中复制带有导出类型的所有程序集,也就是说执行目录(Debug / bin)。

只需将bin1目录中的Module1和Module2复制,everthing将正常组成:)

实际上我发现应该复制bin目录中的模块的后期构建事件不起作用。也许是因为你改名了。因此,如果您希望它在构建之后自动复制程序集,只需用以下内容替换实际的构建后事件:

copy "$(TargetDir)\$(TargetFileName)" "$(TargetDir)\..\..\..\Shell\bin\$(ConfigurationName)\"

答案 1 :(得分:1)

我已经多次遇到这个问题了,解决它真的很简单。

从模块中删除构造函数。 Prism模块的激活方式与经典导出类型的激活方式不同,因此模块无法使用ImportingConstructor导入所需的服务。而是使用Initialize方法中的ServiceLocator对它们进行初始化。

这将有效:

[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>());
    }
}

我也认为这种行为令人不安。

答案 2 :(得分:0)

我遇到了同样的问题,我的模块Initialize()方法没有被调用...我意识到我在我的Initialize方法中没有使用“override”关键字,该方法在Module基类中声明为虚拟所有我的模块继承自......添加“覆盖”并且它有效!