如何强制为我所有的ViewModels清理()(How to force Cleanup() for

2019-07-30 13:04发布

我的视图模型实例资源的程序退出时必须被释放。

这在我所有的ViewModels:

public class MainViewModel : ViewModelBase
{
    LocalServer Server { get; set; }
    Resource MyResorce { get; set; }

    public MainViewModel(LocalServer server)
    {
        this.Server = server;
        MyResource = new Resource();
    }

    public override void Cleanup()
    {
        if (MyResource != null)
            MyResource.Close();

        MyResource = null;
        base.Cleanup();
    }
}

这ViewModelLocator

public class ViewModelLocator
{
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
        SimpleIoc.Default.Register<MainViewModel>();
    }

    public MainViewModel MainVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MainViewModel>();
        }
    }

    public static void Cleanup()
    {
        // Wrong!! The collection is empty!
        foreach (ViewModelBase vm in ServiceLocator.Current.GetAllInstances<ViewModelBase>() )
            vm.Cleanup();

        SimpleIoc.Default.Unregister<MainViewModel>();

        Messenger.Reset();
    }
}

但是我注意到ServiceLocator.Current.GetAllInstances<MainViewModel>()返回给定视图模型的所有实例,但如果我问ServiceLocator.Current.GetAllInstances<ViewModelBase>()就像这个例子,它返回一个空的集合!

因此,它是只用一个可能的foreach调用清理()我所有的ViewModel?

非常感谢。

Answer 1:

你将不能够做到这一点一气呵成。 这是因为:

在内部,SimpleIoc对象包含实例的词典:

Dictionary<Type, Dictionary<string, object>> _instancesReDictionary<Type, Dictionary<string, object>> _instancesRegistrygistry

当你调用GetAllInstances所发生的情况下,发动机罩是:

public IEnumerable<TService> GetAllInstances<TService>()
        {
            var serviceType = typeof(TService);
            return GetAllInstances(serviceType)
                .Select(instance => (TService)instance);
        }

这反过来又来电:

public IEnumerable<object> GetAllInstances(Type serviceType)
        {
            lock (_factories)
            {
                if (_factories.ContainsKey(serviceType))
                {
                    foreach (var factory in _factories[serviceType])
                    {
                        GetInstance(serviceType, factory.Key);
                    }
                }
            }

            if (_instancesRegistry.ContainsKey(serviceType))
            {
                return _instancesRegistry[serviceType].Values;
            }


            return new List<object>();
        }

基本上,只要它做的是检查,看看你的类型中的一个或多个字典存在。 这是一个直接比较,以便对象是否从一个对象B继承不考虑。

你可以做什么,这需要更多的努力,但会做你想做的,是使用Messenger发送“清理”消息到所有订阅的ViewModels的:

ViewModelLocator:

 public static void Cleanup()
    {

        Messenger.Default.Send<CleanUp>(new CleanUp());
    }

视图模型:

public class MainViewModel : ViewModelBase
{
    public MainViewModel(LocalServer server)
    {
        this.Server = server;
        Messenger.Default.Register<CleanUp>(this,CallCleanUp);
    }
private void CallCleanUp()
{
    CleanUp();
}

这将工作。 如果你想让它自动然后创建一个从ViewModelBase已经在它这个逻辑继承的类,并拥有所有你其他的ViewModels从这个类,而不是继承ViewModelBase。



文章来源: How to force Cleanup() for all my ViewModels
标签: mvvm-light