C# 与Autofac通用接口的工厂
我在Autofac容器中注册了一个实现。我希望能够向Autofac注册以下类并能够对其进行实例化:C# 与Autofac通用接口的工厂,c#,generics,autofac,C#,Generics,Autofac,我在Autofac容器中注册了一个实现。我希望能够向Autofac注册以下类并能够对其进行实例化: public class Test { public Test(ILogger<Test> logger) { logger.LogInformation("Works!"); } } 但我不知道如何处理通用的。有什么建议吗 更新:在阅读了更多内容后,我提出了以下建议: public class LoggingModule: Autofac.M
public class Test
{
public Test(ILogger<Test> logger)
{
logger.LogInformation("Works!");
}
}
但我不知道如何处理通用的。有什么建议吗
更新:在阅读了更多内容后,我提出了以下建议:
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 });
}
}
公共类日志模块:自动传真模块
{
私有只读MethodInfo mi;
公共日志模块()
{
this.mi=typeof(LoggerFactoryExtensions)
.GetMethod(nameof(LoggerFactoryExtensions.CreateLogger),新[]{typeof(ILoggerFactory)});
}
受保护的覆盖无效AttachToComponentRegistration(IComponentRegistry ComponentRegistration,IComponentRegistration注册)
{
注册。准备+=组件准备;
}
组件准备中的私有void(对象发送方,准备事件参数e)
{
e、 参数=e.Parameters.Union(
新[]
{
新解析参数(
(p,i)=>IsGenericLoggerParameter(p.ParameterType),
(p,i)=>CreateLogger(this.mi,p.ParameterType,i.Resolve())
)
});
}
私有静态bool IsGenericLoggerParameter(类型parameterType)
{
返回parameterType.IsGenericType&¶meterType.GetGenericTypeDefinition()==typeof(ILogger);
}
私有静态对象CreateLogger(MethodInfo mi,类型typeArg,ILoggerFactory loggerFactory)
{
类型genericArg=typeArg.GetGenericArguments().First();
MethodInfo generic=mi.MakeGenericMethod(新[]{genericArg});
返回generic.Invoke(null,new[]{loggerFactory});
}
}
然后:
containerBuilder.RegisterType<Test>().AsSelf();
containerBuilder.RegisterModule<LoggingModule>();
var container = containerBuilder.Build();
var test = container.Resolve<Test>();
containerBuilder.RegisterType().AsSelf();
containerBuilder.RegisterModule();
var container=containerBuilder.Build();
var test=container.Resolve();
工作。问题是,我不完全理解它是如何工作的(更重要的是,它可能如何破裂),所以我仍然在寻找更优雅和/或更容易理解的解决方案。我找到了一个简单的答案,但仅适用于
Microsoft.Extensions.Logging
包中的ILogger
:使用Microsoft.Extensions.DependencyInjection
包中的ServiceCollection
:
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>();
IServiceCollection服务=newServiceCollection();
services.AddLogging();//所有的魔法都发生在这里
//设立其他服务
var builder=new ContainerBuilder();
生成器。填充(服务);//从Autofac.Extensions.DependencyInjection包
IContainer容器=builder.Build();
Test t=container.Resolve();
很高兴您发布了以下内容:
以你为例,我让它为伊洛格和伊洛格工作
public class LoggingDependencyRegistrationModule : Autofac.Module
{
private readonly ILoggerFactory _lf;
private readonly MethodInfo _mi;
private readonly Type _t;
public LoggingDependencyRegistrationModule(ILoggerFactory lf)
{
_lf = lf;
_mi = typeof(LoggerFactoryExtensions).GetMethod(nameof(LoggerFactoryExtensions.CreateLogger), new[] { typeof(ILoggerFactory) });
_t = typeof(ILogger);
}
private void OnComponentPreparing(object sender, PreparingEventArgs e)
{
var t = e.Component.Activator.LimitType;
e.Parameters = e.Parameters.Union(new[]
{
new ResolvedParameter(
(p, i) =>
_t.IsAssignableFrom(p.ParameterType),
(p,i)=>{
if(p.ParameterType == _t)
return _lf.CreateLogger(t.ToString());
return CreateLogger(_mi, p.ParameterType, _lf);
}
)
});
}
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 });
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
registration.Preparing += OnComponentPreparing;
}
protected override void Load(ContainerBuilder builder)
{
builder.RegisterInstance(_lf).SingleInstance();
base.Load(builder);
}
}
使用Autofac并需要将Microsoft ILogger
ContainerBuilder builder = new ContainerBuilder();
var loggerFactory = new LoggerFactory();
//loggerFactory.AddProvider(LogProvider) //If you need another provider than Microsoft logger
builder.RegisterInstance(loggerFactory).As<ILoggerFactory>().SingleInstance();
builder.RegisterGeneric(typeof(Logger<>)).As(typeof(ILogger<>)).SingleInstance();
ContainerBuilder=newcontainerbuilder();
var loggerFactory=new loggerFactory();
//loggerFactory.AddProvider(LogProvider)//如果您需要Microsoft logger以外的其他提供程序
builder.RegisterInstance(loggerFactory).As().SingleInstance();
RegisterGeneric(typeof(Logger)).As(typeof(ILogger)).SingleInstance();
需要注入ILogger
static ContainerBuilder CreateBuilder()
{
var builder=new ContainerBuilder();
builder.RegisterInstance(LoggerFactory.Create(config=>config
.AddConsole()
.SetMinimumLevel(LogLevel.Trace)
));
builder.RegisterGeneric(typeof(Logger)).As(typeof(ILogger));
返回生成器;
}
如果您想用复杂的构造函数逻辑注册泛型服务。。。
至于问题的字面答案:我建议使用RegisterGeneric方法
示例
builder.RegisterGeneric((上下文,类型)=>
{
var factory=context.Resolve();
返回factory.CreateLogger(类型[0]。全名);
}).As(类型(ILogger));
您不理解代码的哪一部分?我不理解参数是什么以及它们是如何工作的。
ContainerBuilder builder = new ContainerBuilder();
var loggerFactory = new LoggerFactory();
//loggerFactory.AddProvider(LogProvider) //If you need another provider than Microsoft logger
builder.RegisterInstance(loggerFactory).As<ILoggerFactory>().SingleInstance();
builder.RegisterGeneric(typeof(Logger<>)).As(typeof(ILogger<>)).SingleInstance();