Use a different IoC provider then the built-in when using MvvmCross

As I wrote in an earlier post, MvvmCross has IoC built-in. If you for some reason want to use a different IoC provider then the built-in when using MvvmCross you can write your own provider and use for example Autofac or TinyIoC. This post will show you how to use Autofac.

I create an own project (of type Portable Class Library) so I don’t have to reference Autofac in my core project. I can have it in my client project but then I can’t reference it from other client projects.

In my Autofac resolver I have to implement the IMvxIoCProvider interface and the class has to inherit from MvxSingleton if it should work.

public class AutofacMvxProvider : MvxSingleton<IMvxIoCProvider>, IMvxIoCProvider
    {
        private IContainer _container;
 
        public AutofacMvxProvider(IContainer container)
        {
            _container = container;
        }
 
        public void CallbackWhenRegistered(Type type, Action action)
        {
            _container.ComponentRegistry.Registered += (sender, args) => {
                if(args.ComponentRegistration.Services.OfType<TypedService>().Any( x => x.ServiceType == type))
                {
                    action();
                }
            };
        }
 
        public void CallbackWhenRegistered<T>(Action action)
        {
            CallbackWhenRegistered(typeof(T), action);
        }
 
        public bool CanResolve(Type type)
        {
            return _container.IsRegistered(type);
        }
 
        public bool CanResolve<T>() where T : class
        {
            return _container.IsRegistered<T>();
        }
 
        public object Create(Type type)
        {
            return Resolve(type);
        }
 
        public T Create<T>() where T : class
        {
            return Resolve<T>();
        }
 
        public object GetSingleton(Type type)
        {
            return Resolve(type);
        }
 
        public T GetSingleton<T>() where T : class
        {
            return Resolve<T>();
        }
 
        public object IoCConstruct(Type type)
        {
            return Resolve(type);
        }
 
        public T IoCConstruct<T>() where T : class
        {
            return Resolve<T>();
        }
 
        public void RegisterSingleton(Type tInterface, Func<object> theConstructor)
        {
            var builder = new ContainerBuilder();
            builder.Register(x => theConstructor()).As(tInterface).AsSelf().SingleInstance();
            builder.Update(_container);
        }
 
        public void RegisterSingleton<TInterface>(Func<TInterface> theConstructor) where TInterface : class
        {
            var builder = new ContainerBuilder();
            builder.Register(x => theConstructor()).As<TInterface>().AsSelf().SingleInstance();
            builder.Update(_container);
        }
 
        public void RegisterSingleton(Type tInterface, object theObject)
        {
            var builder = new ContainerBuilder();
            builder.RegisterInstance(theObject).As(tInterface).AsSelf().SingleInstance();
            builder.Update(_container);
        }
 
        public void RegisterSingleton<TInterface>(TInterface theObject) where TInterface : class
        {
            var builder = new ContainerBuilder();
            builder.RegisterInstance(theObject).As<TInterface>().AsSelf().SingleInstance();
            builder.Update(_container);
        }
 
        public void RegisterType(Type tFrom, Type tTo)
        {
            var builder = new ContainerBuilder();
            builder.RegisterType(tTo).As(tFrom).AsSelf();
            builder.Update(_container);
 
        }
 
        public void RegisterType(Type t, Func<object> constructor)
        {
            var builder = new ContainerBuilder();
            builder.Register(x => constructor()).As(t).AsSelf();
            builder.Update(_container);
        }
 
        public void RegisterType<TInterface>(Func<TInterface> constructor) where TInterface : class
        {
            var builder = new ContainerBuilder();
            builder.Register(x => constructor()).As<TInterface>().AsSelf().SingleInstance();
            builder.Update(_container);
        }
 
        public void RegisterType<TFrom, TTo>()
            where TFrom : class
            where TTo : class, TFrom
        {
            var builder = new ContainerBuilder();
            builder.RegisterType<TTo>().As<TFrom>().AsSelf();
            builder.Update(_container);
        }
 
        public object Resolve(Type type)
        {
            return _container.Resolve(type);
        }
 
        public T Resolve<T>() where T : class
        {
            return _container.Resolve<T>();
        }
 
        public bool TryResolve(Type type, out object resolved)
        {
            return _container.TryResolve(type, out resolved);
        }
 
        public bool TryResolve<T>(out T resolved) where T : class
        {
            return _container.TryResolve<T>(out resolved);
        }
    }

To use your own IoC provider you have to override the CreateIocProvider method in your Setup class.

protected override Cirrious.CrossCore.IoC.IMvxIoCProvider CreateIocProvider()
{
            var builder = new ContainerBuilder();
 
            builder.RegisterType<MyType>().As<IMyType>();
 
            var container = builder.Build();
 
            return new AutofacMvxProvider(container);
}

Azure Mobile Services and Autofac

If you want to use an IoC container in your backend hosted in Azure Mobile Services I recommend to use Autofac. The reason is that Autofac already are wired up in Mobile Services and is used by the runtime to resolve references.

Because Autofac already is wired up you cannot create a container as you use to when not hosting in Mobile Services.

To configure how to resolve your references using Autofac in Mobile Services se the code below. The code should be in the register method in the WebApiConfig class. The class can be found in App_Start folder.

ConfigOptions options = new ConfigOptions();
var configBuilder = new ConfigBuilder(options, builder =>
{
      builder.RegisterType<MyImplementation>().As<IMyInterface>();
});
 
HttpConfiguration config = ServiceConfig.Initialize(configBuilder);
configBuilder.ConfigureOwin(config);