开发者

MEF Child Container Module Not Initializing

开发者 https://www.devze.com 2023-04-08 23:38 出处:网络
I have a simple container hierarchy with a parent container which is defined in the Shell MEFBootstrapper using a Directory catalog, and child container(s) which get created off the parent with a dist

I have a simple container hierarchy with a parent container which is defined in the Shell MEFBootstrapper using a Directory catalog, and child container(s) which get created off the parent with a distinct catalog.

My child containers also use DirectoryCatal开发者_JS百科og (different path than parent), and I can see that the container has assembly and part information during runtime.

However, the Initialize() method for the modules located in the child containers are never called.

My goal is to use the child containers as session constructs, allowing the user to create new sessions and toggle between them. But if I cannot get the constituent modules to initialize (and place their views into the regions), I am kind of stuck.

I had thought to raise an event from my session manager using event aggregator to allow the modules to listen for the event and self-initialize, but that doesn't seem to work either.

i. Why isn't Initialize getting called on modules loaded into a child container ii. How can I "trigger" Initialize from the container instance (outside of the module context?) Can you iterate over the assemblies in the container and trigger Initialize that way???

[from MefBootstrapper in shell project]

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

[from the service that manages my sessions (containers)]

    [ImportingConstructor]
    public SessionService(ExportProvider provider)
    {

[constructor for new sessions (containers)]

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

=====

Was asked to include my module code whose initialize method is not called (despite being loaded into the container in question...I can even lazy instantiate the module, but calling Initialize() directly causes the injection operation to fail in the method proper.

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
}

}


I downloaded your code and had a look at it. I immediately found the problem. The bootstrapper is actually getting exports thanks to a DirectoryCatalog like this:

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

This means that you will get the exports from the assemblies in this directory. So you simply need to copy all the the assemblies with the exported types in the directory ".", that is to say the executing directory (Debug/bin).

Just copy Module1 and Module2 in the bin directory and everthing will compose gracefully :)

Actually I found that the post-build events supposed to copy the modules in the bin directory were not working. Maybe because your renamed something. So if you want it automatically copy the assemblies after building just replace the actual post-build event by this one:

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


I already had this problem many times and resolving it is really simple.

Remove the constructor from the your module. Prism modules are not activated the same way it does for classical exported types, therefore modules cannot use ImportingConstructor to import the services you need. Instead intitialize them with the ServiceLocator within the Initialize method.

This will work:

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

I also think that this behavior is kind of disturbing.


I had this same problem where my modules Initialize() method was not being called... I realized I had left off the "override" keyword on my Initialize method that was declared virtual in the Module base class that all of my modules inherit from... added "override" and it worked!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号