Skip to content

Instantly share code, notes, and snippets.

@hamid-shaikh
Created July 14, 2019 08:27
Show Gist options
  • Save hamid-shaikh/24d93419f9b5313685c4dfc40f4b59dc to your computer and use it in GitHub Desktop.
Save hamid-shaikh/24d93419f9b5313685c4dfc40f4b59dc to your computer and use it in GitHub Desktop.
Refit + Prism Forms + Fusillade
public interface IApiService<TInterfaceService>
{
// Use to fetch data into a cache when a page loads. Expect that
// these requests will only get so far then give up and start failing
TInterfaceService Speculative { get; }
// Use for network requests that are fetching data that the user is
// waiting on *right now*
TInterfaceService UserInitiated { get; }
// Use for network requests that are running in the background
TInterfaceService Background { get; }
}
@syahman
Copy link

syahman commented Jul 21, 2020

assalamualaikum. hi.

TInterfaceService <- can u explain this ?

@hamid-shaikh
Copy link
Author

hamid-shaikh commented Jul 21, 2020

@syahman
Walaikum Assalam

Please go through all the steps to get more details.

TInterfaceService - Will be your "service interface", which you have define while doing registration. Please check Step 4
The idea is to get appropriate "Service object" at runtime using IOC. For example if you have below two services.

  1. IAuthenticationService
  2. ISomeDataService

So, Registering to IOC container will be like below.

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    containerRegistry.RegisterSingleton<IApiService<IAuthenticationService>, ApiService<IAuthenticationService>>();
    containerRegistry.RegisterSingleton<IApiService<IAuthenticationService>, ApiService<ISomeDataService>>();
    containerRegistry.RegisterForNavigation<NavigationPage>();
    containerRegistry.RegisterForNavigation<LoginPage, LoginPageViewModel>();
}

Inject required service at ViewModel constructor.

public partial class LoginPageViewModel
{
    public LoginPageViewModel(INavigationService navigationService, 
                              IApiService<IAuthenticationService> authenticationService)
    {
        NavigationService = authenticationService;
        AuthenticationService = authenticationService;//Here you will get AuthenticationService object injected
    }
}

or

public partial class HomePageViewModel
{
    public HomePageViewModel(INavigationService navigationService, 
                              IApiService<ISomeDataService> someDataService)
    {
        NavigationService = authenticationService;
        SomeDataServiceService = someDataService;//Here you will get SomeDataService object injected
    }
}

Also, There are high possibility that your application integrate more than one "Service" providers and this can help you easily identify service provider type.

For example:- Let's say your application is consuming two "Service Provider" for Authentication.
so you can create two Interface like below.

IServiceProvider1
IServiceProvider2

Now, at runtime while creating HttpClient object inside ApiService.cs file you can simply check Interface type and return appropriate HttpClient object.

TInterfaceService CreateHttpClient()
 {
       bool isServiceProvider1 = typeof(TInterfaceService).GetInterface(nameof(IServiceProvider1)) != null;
       HttpClient client;
       if(isServiceProvider1)
      {
           client = new HttpClient(messageHandler)
           {
                 BaseAddress = new Uri(AppConstants.BaseAddressServiceProvider1),
                 Timeout = TimeSpan.FromSeconds(AppConstants.Timeout)
            };
       }
      else
      {
            client = new HttpClient(messageHandler)
           {
                  BaseAddress = new Uri(AppConstants.BaseAddressServiceProvider2),
                  Timeout = TimeSpan.FromSeconds(AppConstants.Timeout)
            };
        }

        client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
        //client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
        return RestService.For<TInterfaceService>(client, new RefitSettings
        {
            ContentSerializer = new JsonContentSerializer(jsonSerializerSettings)
        });
} 

Please let me know if u still have any query.

@syahman
Copy link

syahman commented Jul 22, 2020

dear hamid-shaikh, very thankful for your explanation, now i understand how D.I works in Prism. Being searching this method for almost a week.

i would like to add another nuget to my project instead of Refit + Prism Forms + Fusillade, there will be fody.propertychanged,aritchie Acr.UserDialogs,Polly and Plugin.connectivity. hope this will integrate well with prism. maybe need workaround if i need to inject static interface. so far my prism project able to get API data. what's the difference between RegisterSingleton and RegisterInstance ?

/* Services, D.I */
            containerRegistry.RegisterSingleton<IApiService<IAuthenticationService>, ApiService<IAuthenticationService>>();
            containerRegistry.RegisterInstance(typeof(IUserDialogs), UserDialogs.Instance);

@hamid-shaikh
Copy link
Author

hamid-shaikh commented Jul 22, 2020

@syahman
To understand difference better kindly visit Prism documentation (Very good documentation)

Prism Forms Documentation

One suggestion - Use Xamarin.Essential for Connectivity instead of Plugin.Connectivity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment