Prism.Wpf从自定义Main函数中启动遇到的问题

20 篇文章 2 订阅

最近想整一个插件式开发框架,想把UI做成一个类库,从另外一个类库的Main函数去启动它,当然UI肯定要用到MVVM框架Prism,插件开发时,窗体Show出来还要进行其他一些列的操作,才调用App.Run方法,为了保持运行顺畅,做了不少功课。

之前我写过一篇文章,里面讲解Prism的使用:https://blog.csdn.net/lishuangquan1987/article/details/105014992

通过查看Prism的源码,Container容器是在OnStartup函数中初始化的:
PrismApplicationBase.cs:

/// <summary>
/// The dependency injection container used to resolve objects
/// </summary>
public IContainerProvider Container => _containerExtension;
protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    InitializeInternal();
}
/// <summary>
/// Run the initialization process.
  /// </summary>
  void InitializeInternal()
  {
      ConfigureViewModelLocator();
      Initialize();
      OnInitialized();
  }
 /// <summary>
 /// Runs the initialization sequence to configure the Prism application.
 /// </summary>
 public virtual void Initialize()
 {
     _containerExtension = CreateContainerExtension();
     _moduleCatalog = CreateModuleCatalog();
     RegisterRequiredTypes(_containerExtension);
     RegisterTypes(_containerExtension);
     _containerExtension.FinalizeExtension();

     ConfigureServiceLocator();

     ConfigureModuleCatalog(_moduleCatalog);

     var regionAdapterMappins = _containerExtension.Resolve<RegionAdapterMappings>();
     ConfigureRegionAdapterMappings(regionAdapterMappins);

     var defaultRegionBehaviors = _containerExtension.Resolve<IRegionBehaviorFactory>();
     ConfigureDefaultRegionBehaviors(defaultRegionBehaviors);

     RegisterFrameworkExceptionTypes();

     var shell = CreateShell();
     if (shell != null)
     {
         RegionManager.SetRegionManager(shell, _containerExtension.Resolve<IRegionManager>());
         RegionManager.UpdateRegions();
         InitializeShell(shell);
     }

     InitializeModules();
 }

其中,这一句_containerExtension = CreateContainerExtension();执行创建容器方法,方法是一个虚方法,在PrismApplication中实现:

 protected override IContainerExtension CreateContainerExtension()
 {
     return new UnityContainerExtension();
 }

要自定义Main函数启动,肯定要自己Show窗口,为了能保证用到IOC,窗口的实例需要使用Container对象,也就是在Show窗体之前,Container是要被初始化的。问题就出现在了这里:

OnStartup何时执行

看微软的源码,OnStartup是在Application的构造函数中执行的:

public Application()
{
    EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordGeneral | EventTrace.Keyword.KeywordPerf, EventTrace.Event.WClientAppCtor);
    lock (_globalLock)
    {
        if (_appCreatedInThisAppDomain)
        {
            throw new InvalidOperationException(SR.Get("MultiSingleton"));
        }

        _appInstance = this;
        IsShuttingDown = false;
        _appCreatedInThisAppDomain = true;
    }

    base.Dispatcher.BeginInvoke(DispatcherPriority.Send, new DispatcherOperationCallback(StartDispatcherInBrowser), null);
    base.Dispatcher.BeginInvoke(DispatcherPriority.Send, (DispatcherOperationCallback)delegate
    {
        if (IsShuttingDown)
        {
            return null;
        }

        StartupEventArgs startupEventArgs = new StartupEventArgs();
        OnStartup(startupEventArgs);
        if (startupEventArgs.PerformDefaultAction)
        {
            DoStartup();
        }

        return null;
    }, null);
}

但是,事实是这样的吗??
经过调试发现:
在这里插入图片描述
在执行app.Run的时候才会执行OnStartup
由于app.Run方法是阻塞的,没法在Run之后去show窗体,更没法在Run之后去执行其他操作。

解决办法

1.设置App.xaml生成操作为Page,因为我们不从它启动:
在这里插入图片描述
2.在App的构造函数中主动调用父类的OnStartup方法,就是为了让Container初始化:

public partial class App : PrismApplication
{
     public App()
     {
         base.OnStartup(null);//初始化容器
     }
     protected override void OnStartup(StartupEventArgs e)
     {
         base.OnStartup(e);
     }
     protected override Window CreateShell()
     {
         return null;
     }
    
     protected override void RegisterTypes(IContainerRegistry containerRegistry)
     {

     }
 }

3.编写Main函数:

public  class Test
 {
     [STAThread]
     public static void Main()
     {
         App app = new App();
         app.InitializeComponent();

         var window = app.Container.Resolve<MainWindow>();
         window.Show();

         //执行其他操作,比如加载其他插件,并且与UI交互

         app.Run();
     }
 }

此解决方法的缺陷

缺陷就是,在构造函数中主动调用了父类的OnStartup方法,最后执行app.Run的时候,又会调用一次,貌似没有什么其他问题,但是必须要注意~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值