我有一个 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/