6

My ViewModelは、プログラムの終了時に解放する必要があるリソースをインスタンス化します。

これは私のすべてのViewModelで:

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

しかし、は、指定されたViewModelのすべてのインスタンスを返すことに気付きましたが、この例のようServiceLocator.Current.GetAllInstances<MainViewModel>()に尋ねると、空のコレクションが返されます!!ServiceLocator.Current.GetAllInstances<ViewModelBase>()

したがって、1つのforeachのみを使用してすべてのViewModelに対してCleanUp()を呼び出すことは可能ですか?

どうもありがとう。

4

1 に答える 1

10

これを一度に行うことはできません。理由は次のとおりです。

内部的に、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>();
        }

基本的には、型が 1 つ以上の辞書に存在するかどうかを確認するだけです。これは単純な比較であるため、オブジェクト A がオブジェクト B から継承するかどうかは考慮されません。

あなたができることは、より多くの努力を必要としますが、あなたが望むことをすることです.Messengerを使用して、サブスクライブしているすべてのビューモデルに「クリーンアップ」メッセージを送信します:

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 から継承するクラスを作成し、他のすべてのビューモデルが ViewModelBase ではなくこのクラスから継承するようにします。

于 2012-10-04T14:58:49.240 に答える