Using Autofac in ASP.Net Core 3+. Best practices for controller registration when parameters aren't in container or cannot be resolved automatically

Viewed 246

When working with asp.net core 3 and autofac, if your controller's constructor has some additional parameters, that can not be resolved automatically, there are two (known to me) ways to properly register such controller:

  1. Use WithParameter() method.
  2. Pass a delegate (or lambda expression) that creates an instance of the controller to the Register() method

With all controllers in .net core being registered using InstancePerLifetimeScope(), which way would be a better practice and why?

1 Answers

I think you caring about how to register singular and or multiple parameters automatically while using AutoFac Core in .NetCore 3x environment. In according this acrchitecture i think you have working on MediaTr and Mapster which is the best practice. The below code snippet is from my usage, maybe it can help to imagine

InProgram.cs:

var host = CreateHostBuilder(args).UseServiceProviderFactory(new AutofacServiceProviderFactory()).Build();

In Middleware, startup.cs:

private static void RegisterDomain(ContainerBuilder builder)
{
    var domainAssembly = typeof(ArticleDto).Assembly;

    builder.RegisterType<DesAlgorithm>().As<ICryptAlgorithm>().SingleInstance();
    builder.RegisterType<SHA1Algorithm>().As<IHashAlgorithm>().SingleInstance();
    builder.RegisterType<FastHash>().As<IHash64Algorithm>().SingleInstance();

    // CQRS
    builder.RegisterType<Mediator>().As<IMediator>().InstancePerLifetimeScope();
    builder.Register<SingleInstanceFactory>(ctx =>
    {
        var c = ctx.Resolve<IComponentContext>();
        return t => c.Resolve(t);
    });
    builder.Register<MultiInstanceFactory>(ctx =>
    {
        var c = ctx.Resolve<IComponentContext>();
        return t => (IEnumerable<object>)c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
    });

    Type handlerType = typeof(IHandler);
    builder.RegisterAssemblyTypes(domainAssembly, Assembly.GetExecutingAssembly())
         .Where(t => t.IsClass && !t.IsAbstract && handlerType.IsAssignableFrom(t))
         .AsImplementedInterfaces().PropertiesAutowired().InstancePerLifetimeScope();

    // Repositories
    Type dbContextType = typeof(IDbContext);
    Type repositoryType = typeof(GenericRepository);

    builder.RegisterAssemblyTypes(domainAssembly)
         .Where(t => t.IsClass && !t.IsAbstract && dbContextType.IsAssignableFrom(t))
         .AsSelf().InstancePerLifetimeScope();

    builder.RegisterAssemblyTypes(domainAssembly)
         .Where(t => t.IsClass && !t.IsAbstract && repositoryType.IsAssignableFrom(t))
         .AsImplementedInterfaces().InstancePerLifetimeScope();

}
Related