如何使用SimpleIoc容器处理动态实例(窗口)

时间:2018-11-28 08:31:20

标签: mvvm mvvm-light ioc-container

我是MVVM和IoC的新手。我为此项目使用ViewModel-first方法。我的项目程序集组织如下所示:

  

View(已引用ViewModel
  ViewModel(已引用Model
  Model

一开始工作正常,直到需要Login视图。 Login在程序启动时运行。成功登录后,将显示MainWindowLogin必须自行关闭。可以使用LogoutCommand中的MainWindow进行相反的操作。

我面临的主要障碍是为给定的View类型实例化ViewModel(窗口),而ViewModel不知道其View。在寻找答案时,我发现:

  1. 介体/信使模式。我发现这很方便,我使用此模式显示对话框MessageBox。但是仅出于此目的,我不习惯使用这种模式来处理对象实例化。
  2. 依赖注入。对我来说是一个新概念。但是我可以看到将服务构造函数知识从消费者类中分离出来的真正好处。因此,我通过将SimpleIoc实例注入到View构造函数作为接口并尝试在ViewModel
  3. 上将MVVM-Light ViewModelLocator用作启动器,进行了尝试。
SimpleIoc.Default.Register<IMainWindowView, MainWindow>();  
SimpleIoc.Default.Register<ILoginView, Login>();  
SimpleIoc.Default.Register<LoginVM>();  
SimpleIoc.Default.Register<MainWindowVM>();  

成功登录后,显示MainWindow并关闭Login。但是,当我注销MainWindow以再次显示Login时,我遇到了InvalidOperationException Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed.,因此我认为我需要通过在Window上注销来“清理”由SimpleIoC创建的实例闭幕活动。

public class ViewModelBaseEx : ViewModelBase
{
    protected SimpleIoc Ioc
    {
        get { return SimpleIoc.Default; }
    }

    protected virtual void Unregister<T>() where T : class
    {
        Cleanup();

        if (Ioc.IsRegistered<T>())
        {
            // Attempt to remove instance
            Ioc.Unregister<T>(); 

            // If i still need to show this window again, 
            // shouldn't i need to have this instance available? (not sure)
            Ioc.Register<T>();   
        }                
    }        
}

A,上述解决方法不起作用,现在我不知道该怎么办。

  1. 我的方法的优点/缺点是什么?
  2. 如何使用IoC容器处理动态实例?

更新

取消注册后似乎需要注册,因为如果仅保留未注册的类型,则找不到该类型。至于问题,似乎我也需要注销View类型。因此,我在View(窗口)

中添加了一些代码
private void MainWindow_Closed(object sender, EventArgs e)
{
    SimpleIoc.Default.Unregister<IMainWindowView>();
    SimpleIoc.Default.Register<IMainWindowView, MainWindow>();
}

到目前为止效果很好,这种方法可以接受吗?

0 个答案:

没有答案