使用 Prism Unity 引导程序创建 WPF 应用程序

Posted

技术标签:

【中文标题】使用 Prism Unity 引导程序创建 WPF 应用程序【英文标题】:Creating a WPF application with Prism Unity bootstrapper 【发布时间】:2021-08-20 13:56:26 【问题描述】:

我觉得我看到这个问题问了很多,但是我看到的大多数教程/示例都已经过时了,因为 UnityBootstrapper 类已经过时并且似乎已经被贬值了。我似乎只能找到PrismBootstrapper,它没有实现与UnityBootstrapper 相同的功能。

谁能给我一个如何使用PrismBootstrapper 的例子,或者指出我在尝试从UnityBootstrapper 派生时做错了什么?

我正在尝试遵循本教程: https://www.c-sharpcorner.com/blogs/creating-a-first-wpf-application-using-prism-library-and-mvvm-architectural-patternstep-by-step2

编辑:这是我需要让 MVVM Prism.Unity with Bootstrapper 工作。我不明白如何正确配置 IModuleCatalog 或 RegisterTypes。我还是不太明白 RegisterTypes 是做什么的,或者如何使用我注册的接口。

    我创建了 2 个项目。名为 MRC 和 AlertsLogger 的主项目(WPF 应用程序(.NET Framework))。

    这是我的引导程序的代码。这是设置为在运行时运行而不是打开窗口。

using System;
using System.Windows;
using AlertsLogger.Interfaces;
using MRC.Framework.Core.Data.Connectivity;
using Prism.Ioc;
using Prism.Modularity;
using Prism.Unity;
using Unity;

namespace MRC

    [Obsolete]
    public class BootStrapper : PrismBootstrapper
    

        #region Override Methods
        
        protected override DependencyObject CreateShell()
        
            return Container.Resolve<Shell>();
        

       protected override void RegisterTypes(IContainerRegistry containerRegistry)
       
            containerRegistry.RegisterInstance<IListener>(new Listener());
            containerRegistry.RegisterInstance<IConnectionProvider>(new ConnectionProvider());
            containerRegistry.RegisterInstance<ISettingsProvider>(new SettingsProvider());
       

        protected override void InitializeShell(DependencyObject shell)
        
            base.InitializeShell(shell);
            App.Current.MainWindow = (Window)shell;
            App.Current.MainWindow.Show();
        

        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        
            base.ConfigureModuleCatalog(moduleCatalog);
            Type ModuleLocatorType = typeof(AlertsLogger.ModuleLocators);
            moduleCatalog.AddModule(new Prism.Modularity.ModuleInfo
            
                ModuleName = ModuleLocatorType.Name,
                ModuleType = ModuleLocatorType.AssemblyQualifiedName
            );
        
        #endregion
    


    在 AlertsLogger 项目中,我必须创建一个名为 ModuleLocators 的类。
 public class ModuleLocators : IModule
    
        #region private properties        
        /// <summary>        
        /// Instance of IRegionManager        
        /// </summary>        
        private IRegionManager _regionManager;

        #endregion

        #region Constructor        
        /// <summary>        
        /// parameterized constructor initializes IRegionManager        
        /// </summary>        
        /// <param name="regionManager"></param>        
        public ModuleLocators(IRegionManager regionManager)
        
            _regionManager = regionManager;
        
        #endregion

        #region Interface methods        
        /// <summary>      
        /// Initializes Welcome page of your application.      
        /// </summary>      
        /// <param name="containerProvider"></param>      
        public void OnInitialized(IContainerProvider containerProvider)
        
            _regionManager.RegisterViewWithRegion("Shell", typeof(Views.LoggerDataView));

        
       

        /// <summary>        
        /// RegisterTypes used to register modules        
        /// </summary>        
        /// <param name="containerRegistry"></param>        
        public void RegisterTypes(IContainerRegistry containerRegistry)
        
        
        #endregion
    

【问题讨论】:

您不想创建自己的容器,而是在RegisterTypes 中使用提供者IContainerRegistry 好的,我对其进行了编辑以将其添加到IContainerRegistry,但我不确定如何使用它。我知道如果我创建一个类,比如说TestClass 并创建一个构造函数public TestClass(Interface InterfaceName) 它应该通过,但是我需要在该类中创建一个新实例还是应该通过注册来处理实例? 如果你解析TestClass,容器将尝试解析InterfaceName,并在其中放置一个实例,如果它知道要使用哪个实例。它还将负责生命周期管理,例如单例或瞬态实例。您必须为要解析的所有接口注册实现,具体类型会自动解析...但这确实是一个很大的领域,最好阅读一些有关依赖注入和控制反转的书籍... 【参考方案1】:

只要它存在,您就可以使用UnityBootstrapper,而且实际上有充分的理由这样做(想到集成测试)。

如果您不想使用它,您可以让您的 App(在 App.xaml 中)从 PrismApplication 的 Unity 版本(包括UnityBootstrapper(但每个进程仅限于一个实例,这实际上会扼杀 Specflow-testing)。

App.xaml:

<unity:PrismApplication x:Class="WpfApp1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:unity="http://prismlibrary.com/"
             x:ClassModifier="internal" />

App.xaml.cs:

internal partial class App

    protected override void RegisterTypes( IContainerRegistry containerRegistry )
    
        // ...
    

    protected override Window CreateShell()
    
        // ...
    

旁注:您不会创建自己的容器实例(至少在 99.9% 的情况下),而是使用作为参数提供给 RegisterTypesIContainerRegistry。它只是所用容器的包装器,所以如果您在切换容器时既没有发现文档也没有发现一致的行为,请不要感到惊讶。好消息是你可以在它上面使用GetContainer扩展方法来获取真正的容器。

【讨论】:

您查看我发送的链接了吗?我之所以问,是因为还有其他功能,例如:Public override void Run(runWithDefaultConfiguration)只给了我&lt;unity:DialogWindow/&gt;的选项 @IShouldKnowThis:那么您在设置方面遇到了什么问题? 好的,我们将使用带有引导程序的 Project1 的 ExampleApplication。在RegisterTypes 中,我会做类似UnityContainer container = new UnityContainer() 的事情,然后我会添加类似container.RegisterInstance&lt;?&gt;(?) 的内容,我不确定里面有什么或它到底在做什么。还是应该注册一个接口的实例?喜欢Public Interface Testingpublic string TestInterfaceget;set; 您不应该在RegisterTypes 中创建容器。您将获得对 IContainerRegistry 的引用,您可以使用它来注册您的类型。 你能给我看一个应该在这两个覆盖中使用的代码示例吗?或者可能给我发一个链接到当前的例子?

以上是关于使用 Prism Unity 引导程序创建 WPF 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

使用Prism 7.1,x在UnityContainer中注册模拟对象以进行单元测试

C# WPF MVVM模式Prism框架从零搭建(经典)

PRISM WPF - 导航每次都会创建新视图

C# / WPF / Prism : 关于如何创建包含其他动态区域的动态棱柱区域的建议

在 Wpf 应用程序中使用 Prism 进行导航

Prism.WPF -- Prism框架使用(上)