Click here to Skip to main content
15,884,099 members
Articles / Mobile Apps / Xamarin

Xamarin Forms – Jumpstart Your App With Autofac

Rate me:
Please Sign up or sign in to vote.
2.33/5 (2 votes)
21 Jan 2023CPOL3 min read 7.3K   1   3
Jumpstart app with Autofac
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.

  1. 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.)
  2. 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.
  3. Assign your scope to these static variables on the types that support it.
  4. 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

C#
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
   {
       protected override void OnCreate(Bundle savedInstanceState)
       {
           var builder = new ContainerBuilder();
           // TODO: add your registrations in!
           var container = builder.Build();
           var scope = container.BeginLifetimeScope();
           // the static variable I decided to use is called "_autofacHack"
           // so that it deters people from using it unless they know
           // what it's for! You could use reflection to find similar
           // fields with something like an attribute if you wanted.
           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:

C#
public sealed class MyActivityThatNeedsDependencyInjection : Activity
{
    private static readonly ILifetimeScope _autofacHack;
    private readonly IMyService _theServiceWeWant;
    // NOTE: We kept the constructor PARAMETERLESS because we need to
    public MyActivityThatNeedsDependencyInjection ()
    {
        _theServiceWeWant= _autofacHack.Resolve<IMyService>();
    }
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        // now we can use this service that we "injected"
        _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:

  • Minimize where “ugly” code is. A globally accessible scope on a static class seems like it can spread the “ugly” code to too many spots. This approach is intended to help minimize that.

    What are some next steps to make that EVEN better? Maybe an attribute so we can call it something nicer?

  • Write code that feels as close as possible to the “real” thing. Autofac usually allows us to specify services in the constructor and then automatically allows us to get the instances we need. This code is structured to be very similar, but since we’re NOT allowed to change the parameterless constructors, we resolve our services off the container there instead. And because it’s in the constructor, we can assign things to readonly variables as well which is a nice bonus.

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?

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader Microsoft
United States United States
I'm a software engineering professional with a decade of hands-on experience creating software and managing engineering teams. I graduated from the University of Waterloo in Honours Computer Engineering in 2012.

I started blogging at http://www.devleader.ca in order to share my experiences about leadership (especially in a startup environment) and development experience. Since then, I have been trying to create content on various platforms to be able to share information about programming and engineering leadership.

My Social:
YouTube: https://youtube.com/@DevLeader
TikTok: https://www.tiktok.com/@devleader
Blog: http://www.devleader.ca/
GitHub: https://github.com/ncosentino/
Twitch: https://www.twitch.tv/ncosentino
Twitter: https://twitter.com/DevLeaderCa
Facebook: https://www.facebook.com/DevLeaderCa
Instagram:
https://www.instagram.com/dev.leader
LinkedIn: https://www.linkedin.com/in/nickcosentino

Comments and Discussions

 
GeneralMy vote of 1 Pin
Sacha Barber23-Jan-23 1:40
Sacha Barber23-Jan-23 1:40 
QuestionHmm service location is not IOC Pin
Sacha Barber23-Jan-23 1:39
Sacha Barber23-Jan-23 1:39 
AnswerRe: Hmm service location is not IOC Pin
Dev Leader29-Jan-23 18:00
Dev Leader29-Jan-23 18:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.