Wednesday, April 22, 2015

Simple C# Dependency Resolver, or the beginning of your own IoC container

It's kind of pointless to write your own IoC container in C# seeing that there's

It's kind of pointless to write your own IoC container in C# seeing that there's probably a 100 out there at this point. With that said, there are occasions like the project I'm in now where you plan on some point pulling in a popular controller, but you need something basic to register and resolve instances of interfaces throughout the existing code base in the mean time.

The idea is this:

You have viewModels or controllers that need services, clients, other controllers, whatever.

You could just not care about clean code and do this:

public class MainViewModel()
{
    private readonly IService _service;
    private readonly IDataSource _source;
    public MainViewModel() {
        _service = new Service();
        _source = new Source(service);
    }

    void go() {
        _service.CallAPI();
    }   
}

No big deal. But you start doing this in multiple controllers, viewModels, and then the issue comes up where now you've changed the IDataSource instance you want to use to

new SQLiteSource(service);

So you either go through each class where you're instantiating this Source and change the line, or do what you should have done from the get go following SOLID principles and make the change in one place.

This example below is what you'd do in a Xamarin.Forms app. You start at the base of the project structure, so for Xamarin it's a class called App.

public class App : Application
{
    public App()
    {
        registerDependencies();
        var mainView = new MainView();
        var navPage = new NavigationPage(mainView);
        this.MainPage = navigation;
    }

    void registerDependencies() {
        DependencyResolver.RegisterInstance<IService>(new LoginService());
        var service = DependencyResolver.Resolve<IService>();
        DependencyResolver.RegisterInstance<IDataSource>(new SQLiteSource(service));
    }        
}

public class MainViewModel()
{
    private readonly IService _service;
    private readonly IDataSource _source;
    public MainViewModel() {
        _service = DependencyResolver.Resolve<IService>();
        _source = DependencyResolver.Resolve<IDataSource>();
    }

    void go() {
        _service.CallAPI();
    }   
}

That's it. Now any class that needs an implementation of an interface (of course you need to register at the startup), you just pass the responsibility to your Resolver class, which is below:

public static class DependencyResolver
{
    private static readonly Dictionary<Type, object> _map = new Dictionary<Type, object>();

    public static void RegisterInstance<T>(object instance) {

        if (!_map.ContainsKey(typeof(T))) {
            _map.Add (typeof(T), instance);
        }
    }

    public static T Resolve<T>() {
        if (_map.ContainsKey(typeof(T))) {
            return (T)_map [typeof(T)];
        } else {
            throw(new KeyNotFoundException ());
        }
    }
}

4 comments:


  1. Thank you for sharing a great example of the script! I had some problems with this task and your article helped me cool!
    Richard Brown virtual data room software

    ReplyDelete
  2. The teaching of Economics Essay Writing Service UK is most highly potential for student to get maximum educational benefits.

    ReplyDelete
  3. The usual essays online service that tries to resolve the factor of dependency

    ReplyDelete

Mvvm on Mobile?

Here's my talk from Houston Tech Fest 2017. Recorded Talk: Slides: https://speakerdeck.com/markawil/mvvm-and-mobile-dont-do-it...