[英]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個部分的解決方案:
將使用IMyService的ViewModel 訂閱到MyServiceChangedEvent(首先應實現它)。 在處理程序中,您可以通過ServiceLocator或事件參數更改實現,提高PropertyChanged以更新數據綁定,並針對您的案例執行其他操作。
public class MyServiceChangedEvent : CompositeWpfEvent<IMyService> { }
在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.