DryIoc switch between fake and real service implementation (Xamarin Forms)VS2017

319 Views Asked by At

I have a situation where I want to switch between "FakeService" and "RealService" at runtime.

MyViewModel

    public class BookingViewModel 
    {
        private readonly IBookingService bookingService;

        public WelcomePageViewModel(
            INavigationService navigationService,IBookingService bookingService)
        {
            this.bookingService= bookingService;
        }
     }

In my App.xaml I do as follows:

    private IContainer container;
    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        container = containerRegistry.GetContainer();

        RegisterRealServices()
    }

    private void RegisterRealServices()
    {
        container.Register<IBookingService, RealBookingService>(Reuse.Singleton);
    }

user presses a menu option to use fake services now.So Unregister the real ones and use the fake one.

However what I have done below does not seem to work because I keep getting redirected to the "RealBookingService" and not to the "FakeBookingService"

How can I do it?

    private void RegisterFakeServices()
    {
        container.Unregister<IBookingService>();

        container.Register<IBookingService,FakeBookingService>(
            Reuse.Singleton,
            ifAlreadyRegistered: IfAlreadyRegistered.Replace);
    }

Question: Is it possible to switch service implementation at runtime? How do you do it using DryIoc?

2

There are 2 best solutions below

2
On BEST ANSWER

I am not an expert in Xamarin, but un(re)registering in DryIoc requires a special preparation (specifically for singleton). That's because service creation may be already cached.

Here is the wiki explaining this in detail: https://bitbucket.org/dadhi/dryioc/wiki/UnregisterAndResolutionCache

2
On

You should prevent removing or replacing registrations from your container once you've used it to resolve instances from—that leads to complications and can result in very subtle, hard to track bugs, as both instances and the way their object graphs are constructed can be cached in a DI Container. You should prefer keeping your object graphs fixed, thus not changing the shape of the graphs at runtime.

The solution is to build a new IBookingService service implementation that depends on both the FakeBookingService and RealBookingService and forwards incoming calls to either one of them, based on runtime information (your switch). This is an implementation of the Proxy pattern:

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