Nathan Evans' Nemesis of the Moment

A simple stereotypical JavaScript-like “debounce” service for F#

Posted in .NET Framework, F#, Xamarin by Nathan B. Evans on August 9, 2014

I needed a simple way to throttle / debounce a text box on Xamarin.Forms to protect against fast user input events. It is basically a text “Entry” control linked to a “ListView” that displays somewhat expensive to compute results from a SQLite database. When a user is typing in their query it would cause lots of concurrent search queries to be fired off which of course just meant all the queries would run slower and then the results from just one would be used anyway.

So I took a look at the Reactive Extensions library but decided it was a bit too heavy weight for a simple Xamarin mobile app. I tried to find something simpler but came up short. So I took a look at the LoDash.js and Underscore.js libraries to see how these did it but they were littered with mutable and global state – *urgh*.

So I wrote my own using a simple F# agent (MailboxProcessor) and encapsulated it in a type to protect against improper use.

/// Provides a stereotypical JavaScript-like "debounce" service for events.
/// Set initialBounce to true to cause a inject a bounce when first the debouncer is first constructed.
type Debounce(timeout, initialBounce, fn) as self =
    let debounce fn timeout = MailboxProcessor.Start(fun agent -> 
        let rec loop ida idb = async {
            let! r = agent.TryReceive(timeout)
            match r with
            | Some _ -> return! loop ida (idb + 1)
            | None when ida <> idb -> fn (); return! loop idb idb
            | None -> return! loop ida idb
        }
        loop 0 0)

    let mailbox = debounce fn timeout
    do if initialBounce then self.Bounce()

    /// Calls the function, after debouncing has been applied.
    member __.Bounce() = mailbox.Post(null)

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.