Good news is that Autofac, my IoC container of choice, works with Xamarin and even within Portable Class Library. However there is one potential pitfall and it seems it happens at least when you use factories.
Imagine resolving ITubo defined as:
public class Tubo: ITubo { public Tubo(Func<ITubo> tuboFactory) {} } public interface ITubo {}
Note the use of factory through Func<ITubo>. In this case Autofac uses reflection and perhaps some runtime IL code generation. Now, try running the following piece of code on Xamarin.Android:
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<Tubo>().As<ITubo>(); var container = builder.Build(); container.Resolve<ITubo>();
It is simple registration and after that I do resolve the interface. When you run this code it will most probably work. But that’s only because you are running it in Debug configuration. Now try running in in Release configuration. It will most probably throw an exception at you:
Autofac.Core.DependencyResolutionException: An exception was thrown while executing a resolve operation.
Not very informative but at least the call stack shows that problem happens withing System.Core assembly. And it isn’t Autofac’s fault at all.
The reason for the problem is simple but perhaps not the most obvious one. Default project settings are that at Release configuration it cuts out all of the unused code from SDK libraries (Xamarin stuff which is basically all .net BCL) and combines all of the assemblies into a single file - through its linker (at Debug time it uses shared libraries as would .net on Windows). And since Autofac is doing operations at runtime (at least when it comes to factories), linker doesn’t see those and simply cuts off unused types at compilation time to reduce the output size. Read more about Xamarin linking process here:
The nasty part is that you won’t know what types are cut off until you run the application in Release configuration. Remember, always try your applications in Release configuration!
The solution
Anyway, the solution is, as I’ve found out, rather simple. Just instruct linker to leave alone (don’t optimize) System.Core assembly. If you are using Visual Studio the go to Project/Properties, Android Options tab and enter System.Core text into Skip linking assemblies text box. If you are using Xamaring IDE the go to Project/Properies, Build/Android Build tab, Linker subtab and enter the same System.Core into Ignore Assemblies text box (didn’t try this one). That’s it, linker will leave alone that assembly and Autofac will happily run even in Release configuration.
Luckily the difference in output file size isn’t that significant: 450KB in worst case.