【发布时间】:2020-05-01 10:38:50
【问题描述】:
我正在使用 Caliburn.Micro 框架将我正在开发的应用程序更改为 MVVM 模式。
当我习惯了这一点时,起初,我使用 IConductor 接口进行导航,方法是在 MainViewModel 继承 Conductor<object>,然后使用 ActivateItem 方法导航 Screens。
我没有使用容器,而是每次都实例化一个新的 ViewModel。
例如,要导航到 FirstViewModel,我使用的是ActivateItem(new FirstViewModel());
ViewModelel 资源较少,因此这种实现并不引人注目。但是,我发现 ViewModel 实例没有被释放,我已经开始使用 Timers 来检查实例是否仍在运行,并在后台堆积。
从那时起,我尝试了各种实现来控制 ViewModel 的管理方式。 我想要的是能够决定我是引用一个已经实例化的 ViewModel 还是实例化一个新的。 另外,我想决定是处置 ViewModel 还是让它继续运行以便稍后重新连接。
所以,阅读文档,我在 BootStrapperBase 中实现了一个 SimpleContainer
public class Bootstrapper : BootstrapperBase
{
private SimpleContainer _container = new SimpleContainer();
public Bootstrapper()
{
Initialize();
}
protected override void Configure()
{
_container.Instance(_container);
_container
.Singleton<IWindowManager, WindowManager>()
.Singleton<IEventAggregator, EventAggregator>();
GetType().Assembly.GetTypes()
.Where(type => type.IsClass)
.Where(type => type.Name.EndsWith("ViewModel"))
.ToList()
.ForEach(viewModelType => _container.RegisterPerRequest(viewModelType, viewModelType.ToString(), viewModelType));
}
protected override object GetInstance(Type service, string key)
{
var instance = _container.GetInstance(service, key);
if (instance != null)
return instance;
throw new InvalidOperationException("Could not locate any instances.");
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return _container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
_container.BuildUp(instance);
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<ShellViewModel>();
}
}
我认为IoC.Get<FirstViewModel>() 会实例化一个新的 ViewModel 或重用一个打开的 ViewModel,如果它已经实例化的话。
但是,它每次都在实例化一个新的 ViewModel。
另外,我无法弄清楚在激活另一个 ViewModel 时如何处理 ViewModel。 例如,我在 FirstViewModel 上放置了一个 OnDeactivate,它在切换到另一个 ViewModel 时触发,但我不知道应该放什么代码来处理该实例。 我已经尝试过这个安装程序,实现了 IDisposable 接口,但我收到了 System.StackOverflowException。
protected override void OnDeactivate(bool close)
{
Dispose();
Console.WriteLine("deactivated");
}
public void Dispose()
{
base.TryClose();
}
Caliburn.Micro 的 SimpleContainer 还不足以管理 ViewModel,还是我应该研究一种不同的方法?
我知道我似乎在问多个问题,但所有这些问题都与管理视图模型有关的主要问题有关。
阅读文档时,我遇到了 Lifecycle 概念,我认为这个概念可以解决我的问题,但我没有找到进一步的解释。
Caliburn.Micro 上的文档没有提供很多示例,我发现如果没有示例,我很难理解如何正确使用这个框架。
【问题讨论】:
-
如果我理解您只想要一个 ViewModel 实例?如果是这样,为什么不使用 RegisterSingleton 而不是 RegisterPerRequest ?另一件事..您谈到了未使用的实例的处置... GC 完成了它的工作...只需知道您是否将 EventAggregator 与 Caliburn 一起使用,不要忘记取消订阅..仅此而已...视图和链接的视图模型将是垃圾..您可以测试:只需添加析构函数并设置断点
-
只有在必要时垃圾收集器才会做一件事......所以在内存释放之前的时间可能很长......在你总是可以用代码激活 GC 之后
-
实际上,我使用
System.Windows.Forms.Timer来检查该类是否已被销毁,但这样可以使其保持活动状态 -
@Frenchy,我只是在不知道具体细节的情况下复制/粘贴了引导程序配置。那么,RegisterPerRequest 总是创建一个新实例,而 RegisterSingleton 只创建一个实例?
-
在您的 cmets 之后,我重新阅读了有关 SimpleContainer 的文档,它更容易理解
标签: c# wpf mvvm caliburn.micro