Search code examples
c#xamarin.formsreactiveuisplat

In ReactiveUI, how to call GetService for MutableDependencyResolver


I am reading the book You, I and ReactiveUI and my question relates to the source code for the book at https://github.com/kentcb/YouIandReactiveUI. The versions of ReactiveUI and Splat have changed since the code was published and one portion of the code cannot be duplicated in the current versions. I have contacted the author and am still waiting on a response as of this time of posting this question, and so I am submitting this question here.

In App.xaml.cs there is a call to a Registrations.cs class that passes the current mutable dependency resolver:

public App()
{
    this.autoSuspendHelper = new AutoSuspendHelper(this);
    Registrations.Register(Splat.Locator.CurrentMutable);
}

In the Registrations.cs class, there is a line that takes that IMutableDependencyResolver and calls GetService:

public static void Register(IMutableDependencyResolver container)
{
    ...

    var defaultViewLocator = container.GetService<IViewLocator>();

    ...
}

I, too, would like to get the IVewLocator service, but IMutableDependencyResolver no longer has a GetService method.

So my question is, how should this code be modified to have the same functionality?

The Splat.Locator.Current is an IReadonlyDependenyResolver and that does have a GetService method. Should that be used instead? I wasn't sure if I should change to using Splat.Locator.Current in case there was a reason that Splat.Locator.CurrentMutable was used and wanted to make sure that if I changed to using Splat.Locator.Current that it would not introduce anything unexpected.

UPDATE:

Just want to add that, armed with the knowledge from DPVreony's answer that it is typically the same class implementing the two interfaces, I was able to implement some later lines in the Registrations.cs class that I needed.

So, further in that class, there are some lines that register constants. These needed the mutable dependency resolver. So you can just pass both the read only and mutable into the Registrations class and use them where needed, as shown below:

public static void Register(IReadonlyDependencyResolver container, IMutableDependencyResolver mutableContainer)
{

    ...

    var defaultViewLocator = container.GetService<IViewLocator>();

    ...

    mutableContainer.RegisterConstant(viewLocator, typeof(IViewLocator));

    ...

    var defaultActivationForViewFetcher = container.GetService<IActivationForViewFetcher>();
       
    ...
        
    mutableContainer.RegisterConstant(activationForViewFetcher, typeof(IActivationForViewFetcher));
    mutableContainer.RegisterConstant(activationForViewFetcher, typeof(IForcibleActivationForViewFetcher));
}

And then call the method like so:

Registrations.Register(Splat.Locator.Current, Splat.Locator.CurrentMutable);

Solution

  • There was a change in Splat due to how some DI containers behave with registering services (i.e. they keep re-initializing). So get functionality was split off onto the IReadonlyDependenyResolver exposed by Splat.Locator.Current

    It was to encourage the mindset of use the MutableLocator to get everything in place and then after that you should only ever need to read using Splat.Locator.Current so you're fine to use it. Typically it's the same class implementing the 2 interfaces, so it's a semantic change to reduce risks of tearing down the locator by mistake.

    So in short yes Splat.Locator.Current is for GetService

    Hope that all makes sense.