0

I'm migrating from ASP.Net to Asp.Net Core using Autofac.Extensions.DependencyInjection nuget package.

For our logging service we used a Module to set the context of the logger to the type it is injected to:

internal class ContextualLoggingModule : Autofac.Module
{
    /// <summary>
    /// Dummy function which has an argument of <see cref="Core.Log.ILogger"/> type.
    /// </summary>
    /// <param name="logger">The logger.</param>
    public static void DummyFunction(Core.Log.ILogger logger)
    {
        // dummy only method for Load method
    }

    /// <summary>
    /// Loads and initializes the Logger
    /// </summary>
    /// <param name="builder"></param>
    protected override void Load(ContainerBuilder builder)
    {
        // Fake PropertyInfo that has ParameterType = typeof(ILogger), see .Preparing stuff below
        var loggerPropertyInfo = typeof(ContextualLoggingModule).GetMethod(nameof(DummyFunction))?.GetParameters().Single();

        builder.Register((componentContext, parameters) =>
        {
            Func<object> loggerFactory = null;

            // ReSharper disable once UnusedVariable
            var resolvedParameters = parameters.OfType<ResolvedParameter>()
                                               .SingleOrDefault(resolvedParameter =>
                                               {
                                                   return resolvedParameter.CanSupplyValue(loggerPropertyInfo, componentContext, out loggerFactory);
                                               });

            return loggerFactory();
        })
        .As<Core.Log.ILogger>();
    }

    static ResolvedParameter ILoggerCreatorParameter = new ResolvedParameter(
                    (p, i) => p.ParameterType == typeof(Core.Log.ILogger), // For constructor parameters of this type...
                    (p, i) => Logger.CreateFor(p.Member.DeclaringType) // ...return this instance
                );

    /// <summary>
    /// This adds a handler for our ILogger. The Logger will get a SourceContext property which will contain the name of the type the logger is for. Example: class A.B wants an instance of ILogger than that logger will have a SourceContext property with a value of "A.B" which can later be used to see where a log entry came from.
    /// </summary>
    /// <param name="componentRegistry"></param>
    /// <param name="registration"></param>
    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        registration.Preparing += (sender, args) =>
        {
            if (args.Parameters.Any(p => p == ILoggerCreatorParameter))
            {
                return;
            }

            args.Parameters = new Parameter[]
            {
                ILoggerCreatorParameter
            }.Concat(args.Parameters);
        };
    }

The Load method is called, but never the AttachToComponentRegistration method. What am I missing? It worked before the migration to ASP.Net Core

Startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews(ConfigureMvcOptions);

        services.AddSwaggerGen(c => c.EnableAnnotations());
    }

    public void ConfigureContainer(ContainerBuilder builder)
    {
        builder.Register(_ => Container).As<Core.DependencyInjection.IContainer>();
        builder.Register(_ => Configuration).As<Core.Setting.IConfigurationProvider>();

        var registrationManager = new RegistrationManager();
        registrationManager.RegisterDependencies(builder); // Here the logging module is registered
    }

Program.cs:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
        .UseServiceProviderFactory(new AutofacServiceProviderFactory())
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}
Eike S
  • 300
  • 1
  • 11
  • Did you actually set a breakpoint to verify the `AttachToComponentRegistration` isn't being called or are you assuming that based on behavior? Same question for `Load` - are you sure it's called because you set a breakpoint in there and hit it? Did you [notice there's a different way in 6.0+ Autofac to deal with log stuff like this?](https://autofac.readthedocs.io/en/latest/examples/log4net.html) – Travis Illig Jun 22 '22 at 19:12
  • @TravisIllig Yes I checked with breakpoints. Load is called, but AttachToComponentRegistration is never called. Your link is helpfull though and I will try that – Eike S Jun 23 '22 at 06:56

0 Answers0