我有一个简单的容器层次结构,其父容器在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
}
}
答案 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基类中声明为虚拟所有我的模块继承自......添加“覆盖”并且它有效!