How to force Cleanup() for all my ViewModels

My ViewModel instantiate resource that must be released when the program exits.

this in all my 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();
    }
}
this 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 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.

Answers


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.


Need Your Help

Object sent differs from object received

java objectinputstream objectoutputstream

I'm currently working on a file transfer program. However, I'm facing a major problem. I wondered at first why when I received files on one end, it would only create an empty file. I later found ou...

Configuring GCC with FreeRTOS and OpenOCD

gcc embedded pascal freertos openocd

I'm pretty sure this is possible but I'm not sure how to go about it. I'm very new to building with GCC in general and I have never used FreeRTOS, but I'd like to try getting the OS up and running ...