How to force clear () for all my ViewModels

My ViewModel creates a resource that should be released when the program exits.

this is in all my ViewModels models:

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(); } } 

this is in 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(); } } 

But I noticed that ServiceLocator.Current.GetAllInstances<MainViewModel>() returns all instances of this ViewModel, but if I ask ServiceLocator.Current.GetAllInstances<ViewModelBase>() , as in this example, it returns an empty collection !!

So, is it possible to call CleanUp () for all my ViewModel using only one foreach?

Many thanks.

+6
source share
1 answer

You cannot do this at a time. That's why:

Internally, the SimpleIoc object contains an instance dictionary:

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

When you call GetAllInstances, what actually happens under the hood:

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

Which in turn causes:

 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>(); } 

Basically, everything he does is check if your type exists in one or more dictionaries. This is a direct comparison, therefore, does not take into account the object A inherited from the object B.

What you can do, which will take more effort, but will do what you want, uses Messenger to send a β€œCleanup” message to all your view models:

ViewModelLocator:

  public static void Cleanup() { Messenger.Default.Send<CleanUp>(new CleanUp()); } 

ViewModel:

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

It will work. If you want to do this automatically, create a class that inherits from ViewModelBase, which has this logic in it, and you have all other types of models inherited from this class, not ViewModelBase.

+9
source

Source: https://habr.com/ru/post/920957/


All Articles