The Story of My Life

Diary of a noob programmer

Access to ASP.NET Core MVC registered Autofac Container

TL;DR;

It isn’t long, since i struggle to find out how to access DI registered classes in MVC using autofac, and I failed every time, with every phrase.

So, two days ago, I though to myself, let create access point, and it worked. cool, right?

The way i gonna show you, is not officially provided by those who right Autofac, It’s Cheat, a Trick, but it works. Isn’t that enough? Maybe not; so in case you found a better solution feel free to share it with me.

Other solutions:

I list some of the solutions in my mind, that did not worked for me:

  • Create new Container:
    This solution wasn’t good for me, because i had to register many stuff again and again, also changin one Mapping, require you to remember it and change it in all other containers too.
  • Using Resolve, GetServiceor other similar functionalities:
    Why this doesn’t work for me, I’m not sure, it look what i wanted to do, but just as i said, unfortunattely, it didn’t worked for me, if it works for you, Thats Great.
    Here’s sample of resolve

    var builder = new ContainerBuilder();
    builder.RegisterType<MyComponent>().As<IService>();
    var container = builder.Build();
    // Later...
    using(var scope = container.BeginLifetimeScope())
    {
      var service = scope.Resolve<IService>();
    }

     

My Way, The Cheat

The only way rest for me, was to keep a pointer to the container, so I had to option, some static class, somewhere or a Singleton. I did it with a singleton. I made this class not only for Autofac, but for any unpredictable issue that may come later.

Here’s my Singleton:

using System.Diagnostics.CodeAnalysis;
using Autofac;

namespace MyProject
{
    public class GlobalObjects
    {
        #region Singleton
        private static readonly GlobalObjects Instance = null;
        static GlobalObjects()
        {
            Instance = new GlobalObjects();
        }
        private GlobalObjects()
        {
        }

        public static GlobalObjects GetInstance()
        {
            return Instance;
        }
        #endregion

        [SuppressMessage("ReSharper", "IdentifierTypo")] //if you are not using Resharper, you can remove these attributes.
        public IContainer AutofacContainer { private set; get; }

        [SuppressMessage("ReSharper", "IdentifierTypo")]
        public GlobalObjects SetAutofacContainer(IContainer container)
        {
            AutofacContainer = container;

            return Instance;
        }
    }
}

Then i had to pass the Autofac Container reference to my SetAutofacContainer Method of GlobalObjects class.

So i did it after registering the container in Startup.cs file.

...

namespace Judgel.Web
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            ...

            var builder = new ContainerBuilder();
            var dependencyRegistrar = new DependencyRegistrar();
            dependencyRegistrar.Register(builder);
            builder.RegisterType<LayoutService>().As<LayoutService>().InstancePerLifetimeScope();

            builder.Populate(services);
            var container = builder.Build();

            GlobalObjects.GetInstance().SetAutofacContainer(container);

            return container.Resolve<IServiceProvider>();

        }

        ...
    }
}

In the end, you can access it any where, for example i need it in my view, so i call it like this:

@{
    var di = GlobalObjects.GetInstance().AutofacContainer;
    LayoutService layoutService = di.Resolve<LayoutService>();

    var userId = Context.User.GetUserId();
    Person person = layoutService.GetPerson(userId); //model
    ApplicationUser user= layoutService.GetUser(userId);
}
<!DOCTYPE html>
<html lang="en" class="loading">
...
</html>

The first line is what you need, that’s how we access the Autofac Container.
The second line, is what I use, to resolve my desired object.
After that, i just use my object in my desired way, and it will be different in your scenario .

 

Thank you for reading,
Hassan Faghihi.

Leave a Reply

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

*
*
You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>