簡體   English   中英

Prism / Unity使用新的具體類更新已解析/已注入的引用

[英]Prism / Unity update resolved/injected references with new concrete class

我試圖在運行時更改啟動期間注冊的類型的具體類型。 我能夠更新容器和服務定位器。 但是已經存在的視圖模型仍然引用了引導的原始服務。

引導代碼:

container.RegisterInstance<IMyService>(new MyServiceA(), new ContainerControlledLifetimeManager());

ViewModelCode:

public ViewModel(IMyService service)
{
    _service = service;
}

服務更改代碼:

container.RegisterInstance<IMyService>(new MyServiceB(), new ContainerControlledLifetimeManager());

serviceLocator.Resolve返回MyServiceB。 MyServiceA不再存在於容器中。 但是現有的視圖模型仍然引用MyServiceA。

有什么辦法可以使容器更新更新現有/已解決的引用?

更新:也許這個單元測試可以幫助您了解我所表現的行為。

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Microsoft.Practices.Unity;

    namespace UnitTestProject1
    {
        [TestClass]
        public class UnitTest1
        {      
            [TestMethod]
            public void TestUnity()
            {
                // register ServiceA and ViewModel
                var container = new UnityContainer();
                container.RegisterType<IMyService, MyServiceA>();
                container.RegisterType<MyViewModel>();

                // resolve viewmodel
                var viewModel = container.Resolve<MyViewModel>();

                // replace ServiceA with ServiceB
                container.RegisterInstance<IMyService>(new MyServiceB());

                // Assert success, IMyService is MyServiceB
                Assert.AreEqual(container.Resolve<IMyService>().GetType(), typeof(MyServiceB));
                // Assert fails viewmodel still using MyServiceA
                Assert.AreEqual(viewModel.RegisteredService.GetType(), typeof(MyServiceB));
            }
        }    

        public interface IMyService
        {        
        }

        public class MyServiceA : IMyService
        {
        }

        public class MyServiceB : IMyService
        {
        }

        public class MyViewModel
        {
            public IMyService RegisteredService { get; }

            public MyViewModel(IMyService myService)
            {
                RegisteredService = myService;
            }


        }
    }

如果將為IMyService實現代理類 ,則將在每次調用時從ServiceLocator檢索實際實現,則將解決此問題:

public class MyServiceProxy : IMyService
{
    public int DoWork(string someParameter)
    {
        return ServiceLocator.Resolve<IMyService>().DoWork(someParameter);
    }
}

現在,您可以將MyServiceProxy注入到類構造函數中。 另一種方法是將顯式的ServiceLocator調用添加到每個IMyService用法。 但是您應該記住,ServiceLocator會使您的代碼更復雜,因為它隱藏了類依賴關系。

UPDATE

綁定到檢索到的數據的情況提醒了對該事件的反應。 當事件“數據源已更改”在您的系統中引發時,訂閱者(ViewModels)將處理此事件。 它適用於在Prism中實現的EventAggregator類。

然后基於2個部分的解決方案:

  1. 將使用IMyService的ViewModel 訂閱到MyServiceChangedEvent(首先應實現它)。 在處理程序中,您可以通過ServiceLocator或事件參數更改實現,提高PropertyChanged以更新數據綁定,並針對您的案例執行其他操作。

     public class MyServiceChangedEvent : CompositeWpfEvent<IMyService> { } 
  2. 在IMyService上發布新的MyServiceChangedEvent已更改。 您可以在事件內部創建新屬性,以將新的實現傳遞給訂閱者,而不是使用ServiceLocator。

     var newMyService = new MyServiceB(); container.RegisterInstance<IMyService>(newMyService, new ContainerControlledLifetimeManager()); eventAggregator.GetEvent<MyServiceChangedEvent>().Publish(newMyService); 

為什么不只使用命名實例?

        _container.RegisterType<IMyService, MyService>("ServiceA", new ContainerControlledLifetimeManager());
        _container.RegisterType<IMyService, MyOtherService>("ServiceB", new ContainerControlledLifetimeManager());

        _container.Resolve<IMyService>("ServiceA");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM