1

我正在使用 Prism 和 Unity 创建一个应用程序。我使用DirectoryModuleCatalog来从磁盘加载几个模块,这些模块显示在主菜单中,当您单击此特定模块的名称时,该模块的 UI 将被加载。每个模块都是根据 MVVM 模型设计的,因此具有单独的视图和视图模型。

引导程序:

class Bootstrapper : UnityBootstrapper
{
   protected override DependencyObject CreateShell()
   {
        Shell shell = Container.Resolve<Shell>();
        shell.Show();
        return shell;
   }

   protected override void InitializeShell()
   {
        base.InitializeShell();
        App.Current.MainWindow = (Window)this.Shell;
        App.Current.MainWindow.Show();
   }

   protected override void ConfigureContainer()
   {
       base.ConfigureContainer();
       Container.RegisterType<IApplicationMenuRegistry, MenuRegistry>();
       Container.RegisterType<IApplicationCommands, ApplicationCommands>();
       Container.RegisterType<ShellViewModel, ShellViewModel>(new Microsoft.Practices.Unity.ContainerControlledLifetimeManager());

       //****** When I uncomment following line, the HelloWorldModule2 doesn't get initialized ***********
       // Container.RegisterType<HelloWorldModule2ViewModel, HelloWorldModule2ViewModel>(new Microsoft.Practices.Unity.ContainerControlledLifetimeManager());
    }


    protected override IModuleCatalog  CreateModuleCatalog()
    {
        return new DirectoryModuleCatalog() { ModulePath = @"C:\Data\NPC Service Tool\Source\develop\POC\GUIWithPrism\Modules" };

    }
}

模块:

namespace HelloWorldModule2
{
    [Module(ModuleName="HelloWorldModule2")]
    public class HelloWorldModule2 : IModule
    {
        private IApplicationMenuRegistry menuRegistry;
        private HelloWorldModule2ViewModel viewModel;
        private IRegionManager regionManager;
        public HelloWorldModule2(IApplicationMenuRegistry menuRegistry, HelloWorldModule2ViewModel vm, IRegionManager regionManager)
        {
            this.menuRegistry = menuRegistry;
            this.regionManager = regionManager;
            this.viewModel = vm;
        }

        public void Initialize()
        {
            ObservableCollection<ViewObject> views = new ObservableCollection<ViewObject>();
            views.Add(new ViewObject() { Region = RegionName.Right, ViewType = typeof(HelloWorld2View) });
            views.Add(new ViewObject() { Region = RegionName.Left, ViewType = typeof(View2) }); 

            //****** Here the module gets registered in the main menu ******//
            menuRegistry.RegisterModuleMenuItem("HelloWorld2", "Hello World module 2",views,1);
            this.viewModel.Title = "Hello world module 2";
        }
    }
}

查看型号:

namespace HelloWorldModule2.ViewModels
{
    public class HelloWorldModule2ViewModel : NotificationObject
    {
        private string title;

        public string Title
        {
            get { return title; }
            set
            {
                title = value;
                RaisePropertyChanged(() => this.Title);
            }
        }
    }
}

我遇到了以下问题:当我在 Bootstrapper 代码中看到的 Unity 容器中注册视图模型时,我的模块没有被初始化(我在Initialize模块的方法中设置了一个断点,但它从未命中)。如果我删除注册并删除模块构造函数中的 vm 参数,则模块会初始化。

此外,当我使用此模块手动配置模块目录时:

protected override void ConfigureModuleCatalog()
{
   base.ConfigureModuleCatalog();
   ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog;
   moduleCatalog.AddModule(typeof(HelloWorldModule2.HelloWorldModule2));
}

而不是 ,DirectoryModuleCatalog即使注册了视图模型,它也会正确初始化。

4

2 回答 2

1

我担心你误解了模块类的目的。模块类用于注册模块程序集中提供的类。它仅用于基础设施目的。所以不要试图将任何业务逻辑放在模块类中。

您的断点未命中的原因是 DI 容器无法解析注入的类型 HelloWorldModule2ViewModel。您尝试在初始化之前使用 DI 容器,因此初始化过程会因异常而中止。

请查看 Prism 手册并仔细阅读第 2 章。还请查看参考实现。

于 2012-09-19T13:06:45.820 回答
1

我知道这个问题很老,但我遇到了试图研究类似的问题。由于我找不到一个好的答案,我希望在这里留下一个有用的答案。

我正在使用 Prism 和 DirectoryModuleCatalog 加载 IModule 实例以将组件插入我的应用程序。这多年来一直运行良好,但是当我尝试向其中添加一些功能时,我发现我的一个模块没有加载。输出或任何内容中都没有显示异常 - 模块只是不会初始化。dll 本身已加载,我可以使用其中的类,甚至可以动态访问类。

经过大量研究,我偶然发现这个模块在 shell 应用程序的配置文件中引用了一个类(用于加载自定义 sql 提供程序)。当我删除该引用时,模块初始化得很好。这类似于您注释掉上面从模块库中注册类型的代码。

我的结论(未完全验证)是,如果模块库已经加载,那么 DirectoryModuleCatalog 或模块加载器在加载库仅用于反射时会遇到异常,并且不能/不会在模块上运行初始化。这似乎是模块加载器中的一个错误,特别是因为似乎没有生成错误/日志并且它只是默默地失败。尚未深入研究已加载的 Prism 模块以进行确认。

我认为我的解决方案是将自定义 sql 提供程序分离到一个单独的库中,即使我认为我不应该这样做。

于 2019-08-09T20:52:27.660 回答