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);
}

One thought on “Use a different IoC provider then the built-in when using MvvmCross

  1. pat says:

    Nice blog on how to use Autofac as Ioc with mvvmcross… However, I am running in an issue with service registered as lazysingleton:

    For instance, in my core project, mvvmcross generated that code for me when I included the nugget package:

    CreatableTypes()
    .EndingWith(“Service”)
    .AsInterfaces()
    .RegisterAsLazySingleton();

    I have an IFooService and a FooService class.
    if I try to resolve the IFooService:
    IFooService foo = Mvx.Resolve();

    it fails to resolve it saying that FooService cannot be resolve. Now, with autofac, I usually register my singleton via this mechanism:
    builder.RegisterType().As().SingleInstance();

    Unfortunately, the IMvxIoCProvider doesn’t provide a method signature that gives me what I need to register my singleton that way.

    I was wondering if you’ve ran into the same issue, and if so how did you fix it?

    Thanks

    pat

Leave a Reply

Your email address will not be published. Required fields are marked *