In this post, you will see how to jumpstart your app with Autofac.
I love dependency injection frameworks ever since I started using them. Specifically, I’m obsessed with using Autofac and I have a hard time developing applications unless I can use a solid DI framework like Autofac! I’ve recently been working with Xamarin and found that I wanted to use dependency injection, but some of the framework doesn’t support this well out of the box. I was adamant to get something going though, so I wanted to show you my way to make this work.
Disclaimer: In its current state, this is certainly a bit of a hack. I’ll explain why I’ve taken this approach though!
In your Android projects for Xamarin, any class that inherits from Activity
is responsible for being created by the framework. This means where we’d usually have the luxury of passing in dependencies via a constructor and then having Autofac magically wire them up for us isn’t possible. Your constructors for these classes need to remain parameterless, and your OnCreate
method is usually where your initialization for your activity will happen. We can work around that though.
My solution to this is to use a bit of a reflection hack coupled with Autofac to allow Autofac resolutions in the constructor as close as possible as to how they would normally work. A solution I wanted to avoid was a globally accessible reference to our application’s lifetime scope. I wanted to make sure that I limited the “leakage” of this not-so-great pattern to as few places as possible. With that said, I wanted to introduce a lifetime scope as a reference only to the classes that were interested in using Autofac where they’d otherwise be unable to.
- Make a
static readonly
variable in your classes that care about doing Autofac with a particular name that we can lookup via reflection. (An alternative is using an attribute to mark a static variable.) - After building your Autofac container and getting your scope (but prior to using it for anything), use reflection to check all types that have this
static
scope variable. - Assign your scope to these
static
variables on the types that support it. - In the constructors of these classes (keeping them parameterless so the framework can still do its job!), access your
static
scope variable and resolve the services you need.
Here’s what that looks like in code!
MainActivity.cs
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
var builder = new ContainerBuilder();
var container = builder.Build();
var scope = container.BeginLifetimeScope();
foreach (var field in GetType()
.Assembly
.GetTypes()
.Select(x => x.GetField("_autofacHack",
BindingFlags.NonPublic | BindingFlags.Static))
.Where(x => x != null))
{
field.SetValue(null, scope);
}
LoadApplication(scope.Resolve<App>());
}
The class that can take advantage of this would look like the following:
public sealed class MyActivityThatNeedsDependencyInjection : Activity
{
private static readonly ILifetimeScope _autofacHack;
private readonly IMyService _theServiceWeWant;
public MyActivityThatNeedsDependencyInjection ()
{
_theServiceWeWant= _autofacHack.Resolve<IMyService>();
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
_theServiceWeWant.DoTheCoolStuff();
}
}
Summary
Reading this, you might think “well, I don’t want to pollute my Xamarin code with variables that say _autofacHack
, that’s gross”. And I don’t blame you! So this is to serve as a starting point for a greater solution, which I think is something I’ll evolve out for myself and I encourage you to do the same.
Things I’m focused on:
The more implementations of this I go to use, the more I plan to refine it! How have you leveraged Autofac in your Xamarin projects?