Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 与Autofac通用接口的工厂_C#_Generics_Autofac - Fatal编程技术网

C# 与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

我在Autofac容器中注册了一个实现。我希望能够向Autofac注册以下类并能够对其进行实例化:

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中

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的对象现在将获得正确的ILogger

一年后我将回答,为AutoFac v6提供干净的解决方案

如果要添加Microsoft.Extensions.Logging。。。 使用AutoFac添加ILogger(来自Microsoft.Extensions.Logging)最干净的方法是注册Microsoft.Extensions.Logging.ILogger工厂实现和Microsoft.Extensions.Logging.Logger通用类

Logger类是decorator类,位于Microsoft.Extensions.Logging.Abstractations库中,它封装了实际的ILogger实现,但实际上没有实现具体的Logger(控制台Logger、事件日志Logger等)。记录器具有参数类型为ILogger Factory的构造函数,用于创建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();