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 服务实现,它依赖于 FakeBookingServiceRealBookingService,并根据运行时信息 (你的开关)。这是代理模式的实现:

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