c# - Autofac 通用接口(interface)工厂

标签 c# generics autofac

我有一个 ILoggerFactory 在 Autofac 容器中注册的实现。我希望能够使用 Autofac 注册以下类并能够实例化它:

public class Test
{
    public Test(ILogger<Test> logger)
    {
        logger.LogInformation("Works!");
    }
}

为此,我需要能够“教”Autofac 生成实现 ILogger<T> 的实例对于任何类(class) T .有一个 ILoggerFactory扩展方法 CreateLogger<T>() CreateLogger(Type) 能够生成所需类型的实例,但我不知道如何让 Autofac 调用它们。

如果我想要非泛型 ILogger , 我会写

containerBuilder.Register(c => c.Resolve<ILoggerFactory>().CreateLogger("default"))

但我不确定如何处理通用的。有什么指点吗?

更新:阅读更多内容后documentation ,我想到了这个:

public class LoggingModule: Autofac.Module
{
    private readonly MethodInfo mi;

    public LoggingModule()
    {
        this.mi = typeof(LoggerFactoryExtensions)
            .GetMethod(nameof(LoggerFactoryExtensions.CreateLogger), new[] { typeof(ILoggerFactory) });
    }

    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        registration.Preparing += OnComponentPreparing;
    }

    private void OnComponentPreparing(object sender, PreparingEventArgs e)
    {
        e.Parameters = e.Parameters.Union(
            new[]
            {
                new ResolvedParameter(
                    (p, i) => IsGenericLoggerParameter(p.ParameterType),
                    (p, i) => CreateLogger(this.mi, p.ParameterType, i.Resolve<ILoggerFactory>())
                    )
            });
    }

    private static bool IsGenericLoggerParameter(Type parameterType)
    {
        return parameterType.IsGenericType && parameterType.GetGenericTypeDefinition() == typeof(ILogger<>);
    }

    private static object CreateLogger(MethodInfo mi, Type typeArg, ILoggerFactory loggerFactory)
    {
        Type genericArg = typeArg.GetGenericArguments().First();
        MethodInfo generic = mi.MakeGenericMethod(new[] { genericArg });
        return generic.Invoke(null, new[] { loggerFactory });
    }
}

然后:

        containerBuilder.RegisterType<Test>().AsSelf();
        containerBuilder.RegisterModule<LoggingModule>();
        var container = containerBuilder.Build();
        var test = container.Resolve<Test>();

有效。问题是我不完全理解它是如何工作的(更重要的是,它可能会如何崩溃),所以我仍在寻找更优雅和/或更易于理解的解决方案。

最佳答案

我找到了一个简单的答案,但只针对 ILogger<T>来自 Microsoft.Extensions.Logging包装:使用 ServiceCollection来自 Microsoft.Extensions.DependencyInjection包裹:

        IServiceCollection services = new ServiceCollection();
        services.AddLogging(); // all the magic happens here
        // set up other services 
        var builder = new ContainerBuilder();
        builder.Populate(services); // from the Autofac.Extensions.DependencyInjection package
        IContainer container = builder.Build();
        Test t = container.Resolve<Test>();

关于c# - Autofac 通用接口(interface)工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43750179/

相关文章:

c# - 比较多种类型的多个列表的计数?

arrays - typescript 类型检查不适用于数组过滤器

c# - 希望 Autofac 不注册任何具有多个实现的接口(interface)

asp.net-mvc-3 - 如何访问 ASP.NET MVC3 Controller 中的 autofac 容器?

c# - 如何更新内置 Excel 文档属性(文档元数据)

C# REPL 工具;类似控制台的快速编译工具

java - 如何在 Java 中创建与旧列表相同类型的新列表?

c# - 使用 Autofac,如何在调用 RegisterControllers 后在单个 mvc Controller 上启用属性注入(inject)?

c# - Npgsql for c# 如何访问表脚本、 View 、外键和主键并将它们编写出来

c# - TFS 2010 API - 遍历 QueryHistory 中返回的变更集列表太慢了