Nathan Evans' Nemesis of the Moment

Xamarin/MvvmCross + Autofac

Posted in .NET Framework, Software Design, Xamarin by Nathan B. Evans on February 17, 2014

Recently I’ve been doing some Xamarin development and naturally once a mobile app project reaches a certain size you need to factor it away from just a hacky prototype app towards a sustainable design that ticks all the SOLID boxes.

I researched a handful of various approaches to adopting the MVVM pattern, which included:

  • MvvmCross (OSS, also known as “Mvx”)
  • ReactiveUI (OSS, built on top of the excellent Reactive Extensions / RX library)
  • Crosslight (commercial)

At this time the project didn’t warrant spending $999 on Crosslight (and I only assume it must be very good at that price). So I veered towards an OSS solution. ReactiveUI is by far the more elegantly designed when compared to MvvmCross. However its mobile platform support is relatively new and very focused on solving only the MVVM problem. MvvmCross however is more of a framework that helps you in a number of different ways concerning mobile app development, including providing a dependency injection / IOC layer, and numerous platform-specific extensions for Android, iOS etc. MvvmCross is however, in my opinion, a little “rough around the edges” and most definitely has been put together more like a Panzer Tank than a Lotus Elise.

Ultimately I adopted MvvmCross though as it has the greatest level of momentum in the Xamarin ecosystem and this is important I feel.

One big issue with MvvmCross is that it seems to take on the responsibility of providing a really rather crap IOC container implementation. I’m not sure why it doesn’t just depend upon Autofac or TinyIoc or something like that as it seems like 30% of the code in the MvvmCross codebase could be stripped out if it just farmed out that responsibility to another OSS project. Literally everywhere you look in the MvvmCross codebase there are “factory” and “registry” and, uh, “singleton” components everywhere. Maybe Autofac has spoilt me over the years but I honestly can’t remember the last time I had to “hand roll” such a boilerplate component.

So I set about solving this problem by writing a Autofac adapter for MvvmCross. It turned out to be a lot simpler than I first thought, after working through various nuances of MvvmCross.

AutofacMvxIocProvider.cs

I chose to place this type in a separate assembly intended for all my “Autofac for MvvmCross” related extensions. It is a PCL assembly, since Autofac is fully PCL compatible, even with Xamarin.

public class AutofacMvxIocProvider : MvxSingleton<IMvxIoCProvider>, IMvxIoCProvider {
    private readonly IContainer _container;

    public AutofacMvxIocProvider(IContainer container) {
        if (container == null) throw new ArgumentNullException("container");
        _container = container;
    }

    public bool CanResolve<T>() where T : class {
        return _container.IsRegistered<T>();
    }

    public bool CanResolve(Type type) {
        return _container.IsRegistered(type);
    }

    public T Resolve<T>() where T : class {
        return (T)Resolve(typeof(T));
    }

    public object Resolve(Type type) {
        return _container.Resolve(type);
    }

    public T Create<T>() where T : class {
        return Resolve<T>();
    }

    public object Create(Type type) {
        return Resolve(type);
    }

    public T GetSingleton<T>() where T : class {
        return Resolve<T>();
    }

    public object GetSingleton(Type type) {
        return Resolve(type);
    }

    public bool TryResolve<T>(out T resolved) where T : class {
        return _container.TryResolve(out resolved);
    }

    public bool TryResolve(Type type, out object resolved) {
        return _container.TryResolve(type, out resolved);
    }

    public void RegisterType<TFrom, TTo>()
        where TFrom : class
        where TTo : class, TFrom {

        var cb = new ContainerBuilder();
        cb.RegisterType<TTo>().As<TFrom>().AsSelf();
        cb.Update(_container);
    }

    public void RegisterType(Type tFrom, Type tTo) {
        var cb = new ContainerBuilder();
        cb.RegisterType(tTo).As(tFrom).AsSelf();
        cb.Update(_container);
    }

    public void RegisterSingleton<TInterface>(TInterface theObject) where TInterface : class {
        var cb = new ContainerBuilder();
        cb.RegisterInstance(theObject).As<TInterface>().AsSelf().SingleInstance();
        cb.Update(_container);
    }

    public void RegisterSingleton(Type tInterface, object theObject) {
        var cb = new ContainerBuilder();
        cb.RegisterInstance(theObject).As(tInterface).AsSelf().SingleInstance();
        cb.Update(_container);
    }

    public void RegisterSingleton<TInterface>(Func<TInterface> theConstructor) where TInterface : class {
        var cb = new ContainerBuilder();
        cb.Register(cc => theConstructor()).As<TInterface>().AsSelf().SingleInstance();
        cb.Update(_container);
    }

    public void RegisterSingleton(Type tInterface, Func<object> theConstructor) {
        var cb = new ContainerBuilder();
        cb.Register(cc => theConstructor()).As(tInterface).AsSelf().SingleInstance();
        cb.Update(_container);
    }

    public T IoCConstruct<T>() where T : class {
        return (T)IoCConstruct(typeof(T));
    }

    public object IoCConstruct(Type type) {
        return Resolve(type);
    }

    public void CallbackWhenRegistered<T>(Action action) {
        CallbackWhenRegistered(typeof(T), action);
    }

    public void CallbackWhenRegistered(Type type, Action action) {
        _container.ComponentRegistry.Registered += (sender, args) => {
            if (args.ComponentRegistration.Services.OfType<TypedService>().Any(x => x.ServiceType == type)) {
                action();
            }
        };
    }
}

Setup.cs

I’m just showing my MvxAndroidSetup implementation here, but your iOS and Windows Phone etc would obviously look basically the same.

public class Setup : MvxAndroidSetup {
    private static Assembly CoreAssembly { get { return typeof(App).Assembly; } }

    public Setup(Context applicationContext) : base(applicationContext) { }

    protected override IMvxApplication CreateApp() {
        return new App();
    }

    protected override IMvxIoCProvider CreateIocProvider() {
        var cb = new ContainerBuilder();

        // I like to structure my app using Autofac modules.
        // It keeps everything very DRY and SRP compliant.
        // Ideally, these Autofac modules would be held in a separate PCL so they can be used
        // by Android / iOS / WP platforms without violating DRY.
        cb.RegisterModule<InfrastructureModule>();
        cb.RegisterModule<FeaturesModule>();

        // This is an important step that ensures all the ViewModel's are loaded into the container.
        // Without this, it was observed that MvvmCross wouldn't register them by itself; needs more investigation.
        cb.RegisterAssemblyTypes(CoreAssembly)
            .AssignableTo<MvxViewModel>()
            .As<IMvxViewModel, MvxViewModel>()
            .AsSelf();

        return new AutofacMvxIocProvider(cb.Build());
    }
}

Conclusion

This enables me to use Autofac unhindered from my Xamarin mobile apps. It allows the codebase to remain consistent by only using one IOC container, which helps minimise complexity, encourages more DRY code and in the future would lower the barriers to getting more developers up to speed with the whole codebase. Autofac is by far the best IOC container available for .NET and having it available for using in Xamarin when coupled with MvvmCross provides a major improvement in productivity for me.

IoC containers: where you define the seams of applications

Posted in .NET Framework, Software Design by Nathan B. Evans on April 10, 2013

A few colleagues asked me to do a quick write up about the proper use of a IoC container. Particularly concerning what types you DO and DON’T register into the container. So here we go:

Things that you do and don’t wire up into an IoC container.

The big ones, the seams of the application

Components that are inherently cross-cutting concerns, and need to be “available everywhere” for possible injection. Things like:

  • Logging, tracing and instrumentation
  • Authentication and authorization
  • Configuration
  • Major application services (this includes things like the Controllers in a MVC web app)

Components that will be modularised as plug-ins / add-ins, things that get loaded dynamically. Consider using MEF as the discovery mechanism of these components.

Services with multiple implementations that can be “dynamically selected” through some means (app.config, differing registrations per DEBUG and RELEASE modes at compile-time, per-tenant configuration, etc.)

The little ones, the stylistic ones and where you “lean” on the power of your container to provide infrastructure services or as a development aid

Components that require lifetime scoping or management (transactions, sessions, units of work) and other IDisposable-like things that are longer lived than just a one-off use.

Components that are single instance. Never write “static” components.

Components that require testing / mocking out, etc. Note: I consider this to be a “development aid” and not at all mandatory.

When you want an “automatic factory” (Autofac isn’t called that for no reason!). A simple inline Func<ISomeService> expression is cleaner than a going down the stereotypical Java “Enterprise” route of manually rolling out a SomeServiceFactory class each time. Though that’s more as a result of the sad fact that they still don’t have lambdas.

And now the things that you leave out of the container

Anything that is never, and never has any need to be, referenced outside out of the module it is within.

Implementation details of a module. Your container registrations should be the facade that hides the complexities of how that module works.

Things that are essentially just DTOs, entities, POCOs, other dumb types, etc.

Little utility, helper functions.

Note: I refer to “module” a few times. This is in no way in direct reference to an assembly or package. It’s more in reference to a namespace, because components typically reside within a relatively self contained namespace with a container registration module.

Cardinal rules

Never ever call a “static” Kernel.Get / Resolve, or whatever equivalent your container might expose, anywhere. This is not dependency injection. It is service location. Which is a whole different pattern entirely. Autofac is quite neat in that it’s one of very few containers that actually does not, out of the box, provide any sort of “static” resolution/service location function. And that is good.

Only call Get / Resolve methods in your bootstrap code at the root of your object graph. And even then, there should only be less than a handful of such calls. If you can get it down to just one, then you’ve done well and you probably have an object graph that is very well expressed.

Always keep the object graph in the back of your mind. It’s a shame, in my opinion, that containers tend to keep this information hidden away in their internals. The only time you get a glimpse of it is in the exception message for when you’ve inadvertently introduced a circular dependency. Things could be so much better than this.

If you have a component that’s requiring injection of more than about five dependencies, then it should start coming onto your “radar of suspiciousness”. If it reaches about eight to nine dependencies you should almost certainly consider refactoring it and, probably, the wider namespace or module as a whole. I often see this happen on Controllers in MVC applications; the so called “fat controller” problem. Thankfully, because the dependencies are already “well expressed” (it’s just that there is too many of them) then normally refactoring such problem areas of the codebase is a relatively straight forward task.

Nowhere except your bootstrapper and container modules should reference the container, i.e. its namespaces. Arguably, your bootstrapper and container modules can be in a totally separate assembly by themselves and only that assembly holds references to your container’s assemblies. If you’re seeing namespace imports for your container all over your projects then something is very badly wrong.

Avoid the use of “service locator injections”, such as IComponentContext in Autofac. This is one of the very few ways that Autofac supports to allow you to shoot yourself in the foot. It’s not quite as bad as a “static” Kernel.Get style service locator, but it’s still pretty damn bad. As it implies you don’t actually know what possible dependencies your component has, which should be impossible. To avoid this, express your dependencies better. If there are multiple instances you wish to dynamically “select” from at runtime then you can roll your own resolution delegate function and lean on your container to implement it. Autofac makes this very easy using its IIndex relationship. For example:

public delegate IMyService MyServiceResolver(string name);

// ... this stuff below goes in your container module ...
Func<IComponentContext, MyServiceResolver> tmp = c => {
    var indexedServices = c.Resolve<IIndex<string, IMyService>>();
    return name => indexedServices [name];
};

builder.Register(tmp)
       .As<MyServiceResolver>()

builder.Register(c => new MyService())
       .As<IMyService>()
       .Keyed<IMyService>(serviceDescription.Name);
       // The "keyed on" value is a string in this example.
       // But, usefully, it can be any object including value types such as an enum.

// ... any time I want to resolve a IMyService, I can just do this in a constructor:
class SomeOtherComponent {
    private readonly IMyService myService;
    public SomeOtherComponent(MyServiceResolver myServiceResolver) {
        if (myServiceResolver == null)
            throw new ArgumentNullException("myServiceResolver");
        
        this.myService = myServiceResolver("Fred");
        // Technically this is a form of service location.
        // However, because we have constrained the number of services that
        // can be resolved to a particular *type*; then this does not
        // introduce any bad practices to the codebase.
        //
        // Most importantly, we are not relying on any "static" magic.
        // (Which is the absolute hallmark of truly bad service location.)
        // Nor are we holding any references to the container.
    }
}

Example of a Bootstrapper, Container Module and general structure of your Program Root

This is a little snippet of a relatively well structured IoC server application. I added some relevant comments to it.

public class Program {
    private static IContainer Container { get; set; }
    private static ILog Log { get; set; }
    private static ProgramOptions Options { get; set; }
    private static Lazy<HostEntryPoint> Host { get; set; }

    public static void Main(string[] args) {
        try {
            Options = new ProgramOptions();
            if (!Parser.Default.ParseArguments(args, Options))
                return;

            // Root of the program.
            // Bootstraps the container then resolves two components.
            // One for logging services in the root (this) and the other
            // is the *actual* entry point of the application.
            Container = new Bootstrapper().CreateContainer();
            Log = Container.Resolve<ILog>(TypedParameter.From("boot"));
            Host = Container.Resolve<Lazy<HostEntryPoint>>();

            if (Options.RunAsService)
                RunAsService();
            else
                RunAsConsole();

        } catch (Exception x) {
            // Arguably one of the very few places catching a plain
            // Exception can make sense: at the root of the program.
            Log.FatalException("Unexpected error occurred whilst starting.", x);
            Environment.Exit(100);
        }

        Log.Info("Exiting...");
        Container.Dispose();
        Thread.Sleep(500);
    }
    
    // ... cut for brevity ...
}



internal class Bootstrapper {
    public virtual IEnumerable<IModule> GetModules() {
        yield return new LoggingModule {
            Console = LoggingMode.TraceOrAbove,
            File = LoggingMode.WarningOrAbove,
            Debug = LoggingMode.Off,
            RegisterNetFxTraceListener = true
            // Container Modules are an excellent place to pass in
            // certain configuration/runtime parameters and options.
            // I prefer to "hard code" things like this until there
            // is a *real* need to expose such things to a config file,
            // and hence the user of the application.
        };

        // These modules can be specified in any order.
        // Container will resolve the object graph at
        // build-time not at registration-time.

        yield return new QueuesModule() { ConcurrentReceivers = 4 };
        yield return new DispatchersModule();
        yield return new HciCommandsModule();
        yield return new MefModulesModule();
        yield return new AzureDataModule() { ConnectionString = "<goes here>"};
    }
    
    public virtual void RegisterCore(ContainerBuilder builder) {
        builder.Register(c =>
                         new HostEntryPoint(
                             c.Resolve<MefModuleLogging>(),
                             c.Resolve<IEnumerable<IQueueAgent>>(),
                             c.Resolve<IEnumerable<IDispatcher>>()))
               .SingleInstance();
               
        // As well as typically only ever using constructor injection...
        // I prefer to explicitly define the dependency resolutions here, each time.
        // That is, in my opinion, half the point of IoC. You're doing it to keep
        // very close tabs on your dependency graphs. So it should certainly not
        // be the norm that you let the container resolve them through its automagicness.
        // An exception to this rule is dynamically loaded modules (such as MEF assemblies)
        // where you cannot possibly know, at compile-time, what dependencies are required.
    }

    public IContainer CreateContainer() {
        var builder = new ContainerBuilder();

        foreach (var module in GetModules())
            builder.RegisterModule(module);

        RegisterCore(builder);

        return builder.Build();
    }
}

I’m open to feedback and discussion 🙂