Prism/Unity使用新的具体类更新解析/注入的引用
本文关键字:更新 注入 引用 Unity Prism | 更新日期: 2023-09-27 18:27:27
我试图在运行时为启动期间注册的类型更改具体类型。我能够更新容器&服务定位器。但现有的视图模型仍然引用了引导的原始服务。
引导程序代码:
container.RegisterInstance<IMyService>(new MyServiceA(), new ContainerControlledLifetimeManager());
ViewModelCode:
public ViewModel(IMyService service)
{
_service = service;
}
服务更改代码:
container.RegisterInstance<IMyService>(new MyServiceB(), new ContainerControlledLifetimeManager());
serviceLocator.Reve返回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实现Proxy类,它将在每次调用时从ServiceLocator检索实际实现,那么问题就会得到解决:
public class MyServiceProxy : IMyService
{
public int DoWork(string someParameter)
{
return ServiceLocator.Resolve<IMyService>().DoWork(someParameter);
}
}
现在,您可以将MyServiceProxy注入到类构造函数中。另一种方法是向每个IMyService使用添加ServiceLocator的显式调用。但您应该记住,ServiceLocator会使您的代码更难理解,因为它隐藏了类依赖关系。
更新
绑定到检索到的数据的情况会提醒对事件的反应。当事件"数据源已更改"在您的系统中引发时,订阅者(ViewModels)将处理此事件。这是EventAggregator类的工作,它在Prism中实现了。
然后基于两部分的解决方案:
将使用IMyService的ViewModels订阅到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");