Using Autofac with Xamarin

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 within 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:

Linking

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 Xamarin 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.

Powerful and easy installation authoring of .net applications with Advanced Installer

Lately I’ve built a .net class library that supports COM as well. To make setup file I usually use Visual Studio’s Setup Project because I rarely do anything complicated during the installation ant Setup Project does the work fine for me.

This time the setup was a bit different, more complicated, because I needed to register my COM stuff during the installation. So I’ve built the setup file and tried the installation inside VMWare Workstation’s guest as I always do. COM objects were registered fine but type library (TLB) wasn’t registered at all when setup project is built on Vista/Visual Studio 2008. The later isn’t strictly required for running the code but it surely helps developers with strong typing support. There are several options to solve the issue ranging from building on XP to coding the post install/uninstall actions. Well, none of them looks very appealing to me thus I’ve decided to try the Advanced Installer from Caphyon this time.

I can say that creating a setup file for my .net application with Advanced Installer was a breeze – I had a working MSI setup in 10 minutes. The process consisted of importing the Visual Studio Setup Project (which I already had – I could start from scratch or by importing the library project) and adjusting few properties. Truth, mine wasn’t a complicated one but it surely solved type library registration with a click on the checkbox. It actually solved my problem in 10 minutes. Any other option would be either more annoying or it would take more time.

Advanced Installer is not just easy to use. It looks like a powerful and flexible authoring tool as well and certainly not limited to (simple) .net applications only.

ClickOnce and DevExpress components deployment

Let’s say you’ve build a WinForms application and put some DevExpress (or any other 3rd party controls installed in GAC I suppose) controls in there. At some point you have to deploy the application and let’s say you’ll use ClickOnce technology. Its easy, go to Project Properties/Publish tab, select where to publish and click Publish button. The next step is to try the application and of course you try it at your development computer – it works, no surprise there. However, when your client runs it on his computer it will most probably throw some sort of exception at the very beginning. Besides the obvious Murphy law involvement, why’s that? After all it worked on *development* computer.

There are two problems in this process.

1. ClickOnce doesn’t include 3rd party assemblies by default. This is probably true for all 3rd party assemblies that reside in GAC on development computer or in other words, those which are marked with CopyLocal=false (I admit it, I never researched in details). It should include those who are marked CopyLocal=true. Now, if you look at your Application Files in Publish tab of Project Properties you’ll see that all three DevExpress assemblies are marked with Publish Status = Prerequisite (Auto) flag – it means that your application expects those assemblies already installed on target machine:

pre

To include them in your deployment package change their Publish Status flag to Include. Like this:

post

All required assemblies will be published to client’s computer and the application will work, or at least will work as good or as bad as on development computer.

2. Your testing process isn’t good. You should always test deployment scenarios on non-development machine(s). VMWare Workstation is of great help. Besides the great virtualization desktop platform it also support integration in Visual Studio itself so you can pretty easily launch application in guest OS or even remotely debug it and even record the session. The other virtualization option on desktop is MS’ VirtualPC, an inferior application but free. You could use virtualization servers as well (MS HyperV,  VMWare Server, etc.).

That’s it.