n0r*_*0rd 4 c# generics autofac
我ILoggerFactory在 Autofac 容器中注册了一个实现。我希望能够使用 Autofac 注册以下类并能够实例化它:
public class Test
{
public Test(ILogger<Test> logger)
{
logger.LogInformation("Works!");
}
}
Run Code Online (Sandbox Code Playgroud)
为此,我需要能够“教” Autofac 生成实现ILogger<T>任何类的实例T。有一个ILoggerFactory扩展方法CreateLogger<T>(),并CreateLogger(Type)认为能够生产所需类型的实例,但我不能换我围绕着如何使Autofac打电话给他们的头。
如果我想要非泛型ILogger,我会写
containerBuilder.Register(c => c.Resolve<ILoggerFactory>().CreateLogger("default"))
Run Code Online (Sandbox Code Playgroud)
但我不确定如何处理通用的。任何指针?
更新:阅读更多文档后,我想出了这个:
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 });
}
}
Run Code Online (Sandbox Code Playgroud)
进而:
containerBuilder.RegisterType<Test>().AsSelf();
containerBuilder.RegisterModule<LoggingModule>();
var container = containerBuilder.Build();
var test = container.Resolve<Test>();
Run Code Online (Sandbox Code Playgroud)
作品。问题是我不完全理解它是如何工作的(更重要的是,它是如何崩溃的),所以我仍在寻找更优雅和/或更易于理解的解决方案。
我找到了一个简单的答案,但仅适用于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>();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1755 次 |
| 最近记录: |