Search code examples
c#mvvmuwptemplate10uwp-navigation

UWP MVVM Template10: Access single instance of external API across application


I've been tasked with taking over a partially developed sizeable and complex UWP application using MVVM via Template 10. The app needs to use an in-house developed webservices API and this needs to be used for practically every single function, starting with the initial login page.

So given I need to access a single instance of the API everywhere how do I go about doing that correctly? I've used MVVM a fair bit but never used Template10 and never had to share an instance of an object across an entire MVVM UWP app before.

So far I can think of three ways:

  1. Declare and instantiate API instance in Appl.xaml.cs and use it globally
  2. Create a public Globals class and have the instance as a public static property: c# public class Globals { private static OurAPI _ourAPI; public static OurAPI API { get { return _ourAPI; } set { _ourAPI = value; } } }

  3. Instantiate the API in the login page and then pass it as a parameter between ViewModels, presumably using the Navigation service.

I'm thinking 1 or 2 are most likely not MVVM compliant and could cause unit testing issues so maybe 3 is the best option? Or is there another, more correct way to do this to adhere to Template10/MVVM concepts and also be able to unit test it?

EDIT: Sorry about the code not formatting, the edit box formats it Ok but when I save it it goes back to one long sentence :-(


Solution

  • The best solution consists of a singleton service and inversion of control (IoC) / Dependency injection . This is a pretty complex topic so I definitely encourage to read about it from several sources.

    In summary, you first create an interface for your service, where you declare all the public members and methods. Then you create an implementation of the interface. Then you use a IoC container and register your service as a singleton (single-instance) and then integrate the IoC so that it creates instances of your view models. Then you can put the interface as a constructor parameter of your view model and the IoC container will make sure to provide the singleton instance you registered.

    In your case, you are using Template 10 which can be integrated with different IoC containers as seen in the documentation. Check out AutoFac as an example of an IoC container. You can see some examples of registering and resolving a service in the documentation.

    For a general solution, check this SO question which demonstrates using AutoFac in UWP.

    You can also see some code examples in this SO question and this one specifically for Template 10.

    This solution is better than using static and global instances because you never actually deal with any hardcoded reference and actually always work just against the interface. You put the interface as the parameter of your constructor and IoC will take care of providing the instance for you. In addition - you can anytime swap the interface implementation for a different class and you just have to update it in one single location - the IoC registration.