My ViewModel instantiate resource that must be released when the program exits.
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();
}
}
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 a given ViewModel but if I ask ServiceLocator.Current.GetAllInstances<ViewModelBase>()
like in this example it returns an empty collection!!
So, it's possible call CleanUp() for all my ViewModel using only one foreach?
Many thanks.
You won't be able to do this in one go. Here's why:
Internally, the SimpleIoc object contains a dictionary of instances:
Dictionary<Type, Dictionary<string, object>> _instancesReDictionary<Type, Dictionary<string, object>> _instancesRegistrygistry
When you call GetAllInstances what's actually happening under the hood is:
public IEnumerable<TService> GetAllInstances<TService>()
{
var serviceType = typeof(TService);
return GetAllInstances(serviceType)
.Select(instance => (TService)instance);
}
Which in turn calls:
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, all that it's doing is checking to see if your type exists in one or more dictionaries. It's a straight comparison so whether an object A inherits from object B isn't taken into account.
What you could do, which requires more effort, but will do what you want, is use the Messenger to send a "Cleanup" message to all of your subscribing viewmodels:
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();
}
This will work. If you want to make it automatic then create a class that inherits from ViewModelBase that has this logic in it and have all you other viewmodels inherit from this class instead of ViewModelBase.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With