DryIoc虚实切换服务实现(Xamarin Forms)VS2017
DryIoc switch between fake and real service implementation (Xamarin Forms)VS2017
我有一种情况想在运行时在 "FakeService" 和 "RealService" 之间切换。
MyViewModel
public class BookingViewModel
{
private readonly IBookingService bookingService;
public WelcomePageViewModel(
INavigationService navigationService,IBookingService bookingService)
{
this.bookingService= bookingService;
}
}
在我的 App.xaml 中,我的操作如下:
private IContainer container;
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
container = containerRegistry.GetContainer();
RegisterRealServices()
}
private void RegisterRealServices()
{
container.Register<IBookingService, RealBookingService>(Reuse.Singleton);
}
用户按下菜单选项以使用虚假服务now.So注销真实服务并使用虚假服务。
但是我在下面所做的似乎不起作用,因为
我不断被重定向到 "RealBookingService" 而不是 "FakeBookingService"
我该怎么做?
private void RegisterFakeServices()
{
container.Unregister<IBookingService>();
container.Register<IBookingService,FakeBookingService>(
Reuse.Singleton,
ifAlreadyRegistered: IfAlreadyRegistered.Replace);
}
问:是否可以在运行时切换服务实现?你如何使用 DryIoc 做到这一点?
我不是 Xamarin 方面的专家,但在 DryIoc 中取消(重新)注册需要特殊准备(特别是针对单例)。那是因为服务创建可能已经被缓存了。
这里是详细解释这个的 wiki:
https://bitbucket.org/dadhi/dryioc/wiki/UnregisterAndResolutionCache
您应该 prevent removing or replacing registrations 从您的容器中使用它来解析实例 - 这会导致复杂化,并可能导致非常微妙、难以跟踪的错误,因为实例及其对象的方式构建的图形可以缓存在 DI 容器中。您应该更喜欢保持对象图固定不变,从而在运行时不更改图的形状。
解决方案是构建一个新的 IBookingService
服务实现,它依赖于 FakeBookingService
和 RealBookingService
,并根据运行时信息 (你的开关)。这是代理模式的实现:
public class BookingServiceSelectorProxy : IBookingService
{
private readonly FakeBookingService fake;
private readonly RealBookingService real;
public BookingServiceSelectorProxy(FakeBookingService fake, RealBookingService real) {
this.fake = fake;
this.real = real;
}
private IBookingService BookingService =>
/* return fake or real based on your runtime switch */
// All methods dispatch to one of the wrapped repositories
public void CompleteBooking(CompleteBookingRequest request)
=> this.BookingService.CompleteBooking(request);
public void CancelBooking(CancelBookingRequest request)
=> this.BookingService.CancelBooking(request);
}
我有一种情况想在运行时在 "FakeService" 和 "RealService" 之间切换。
MyViewModel
public class BookingViewModel
{
private readonly IBookingService bookingService;
public WelcomePageViewModel(
INavigationService navigationService,IBookingService bookingService)
{
this.bookingService= bookingService;
}
}
在我的 App.xaml 中,我的操作如下:
private IContainer container;
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
container = containerRegistry.GetContainer();
RegisterRealServices()
}
private void RegisterRealServices()
{
container.Register<IBookingService, RealBookingService>(Reuse.Singleton);
}
用户按下菜单选项以使用虚假服务now.So注销真实服务并使用虚假服务。
但是我在下面所做的似乎不起作用,因为 我不断被重定向到 "RealBookingService" 而不是 "FakeBookingService"
我该怎么做?
private void RegisterFakeServices()
{
container.Unregister<IBookingService>();
container.Register<IBookingService,FakeBookingService>(
Reuse.Singleton,
ifAlreadyRegistered: IfAlreadyRegistered.Replace);
}
问:是否可以在运行时切换服务实现?你如何使用 DryIoc 做到这一点?
我不是 Xamarin 方面的专家,但在 DryIoc 中取消(重新)注册需要特殊准备(特别是针对单例)。那是因为服务创建可能已经被缓存了。
这里是详细解释这个的 wiki: https://bitbucket.org/dadhi/dryioc/wiki/UnregisterAndResolutionCache
您应该 prevent removing or replacing registrations 从您的容器中使用它来解析实例 - 这会导致复杂化,并可能导致非常微妙、难以跟踪的错误,因为实例及其对象的方式构建的图形可以缓存在 DI 容器中。您应该更喜欢保持对象图固定不变,从而在运行时不更改图的形状。
解决方案是构建一个新的 IBookingService
服务实现,它依赖于 FakeBookingService
和 RealBookingService
,并根据运行时信息 (你的开关)。这是代理模式的实现:
public class BookingServiceSelectorProxy : IBookingService
{
private readonly FakeBookingService fake;
private readonly RealBookingService real;
public BookingServiceSelectorProxy(FakeBookingService fake, RealBookingService real) {
this.fake = fake;
this.real = real;
}
private IBookingService BookingService =>
/* return fake or real based on your runtime switch */
// All methods dispatch to one of the wrapped repositories
public void CompleteBooking(CompleteBookingRequest request)
=> this.BookingService.CompleteBooking(request);
public void CancelBooking(CancelBookingRequest request)
=> this.BookingService.CancelBooking(request);
}