C# 关于Autofac中间件模块的困惑

C# 关于Autofac中间件模块的困惑,c#,autofac,C#,Autofac,因此,我下面是一个设置LoggerMiddle软件的示例,该示例演示了我只使用.NETCore的ILogger。我们已经有了一个LoggerModule,它在v6之前就可以工作了,所以我将创建代码复制到loggermdware类中以适应这种情况 我不明白的是如何注册这个。模块上没有默认构造函数,因此无法使用builder.RegisterModule()。我知道我可以预先创建MiddlewareModule,然后传入LoggerMiddle的一个实例builder.RegisterModule(

因此,我下面是一个设置LoggerMiddle软件的示例,该示例演示了我只使用.NETCore的ILogger。我们已经有了一个LoggerModule,它在v6之前就可以工作了,所以我将创建代码复制到loggermdware类中以适应这种情况

我不明白的是如何注册这个。模块上没有默认构造函数,因此无法使用
builder.RegisterModule()
。我知道我可以预先创建MiddlewareModule,然后传入LoggerMiddle的一个实例
builder.RegisterModule(moduleInstance)
,但是这个MiddlewareModule应该用于我们创建的所有中间件。这个文档页面没有详细说明最后的细节。我是否只针对每个IResolveMiddleware实例执行此操作

var loggerMiddlewareModule = new MiddlewareModule(new LoggerMiddleware());
builder.RegisterModule(loggerMiddlewareModule);

var otherMiddlewareModule = new MiddlewareModule(new OtherMiddleware());
builder.RegisterModule(otherMiddlewareModule);
我的中间件和模块:

public class LoggerMiddleware : IResolveMiddleware
{
    public PipelinePhase Phase => PipelinePhase.ParameterSelection;

    public void Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
    {
        var t = context.Registration.Activator.LimitType;

        // Add our parameters.
        context.ChangeParameters(context.Parameters.Union(
            new[]
            {
                new ResolvedParameter((p, i) => p.ParameterType == typeof(ILogger), (p, i) => GetLogger(i, t)),
                new ResolvedParameter(
                    (p, i) => p.ParameterType.GenericTypeArguments.Any() &&
                              p.ParameterType.GetGenericTypeDefinition() == typeof(ILogger<>),
                    (p, i) => GetGenericTypeLogger(i, t))
            }));

        // Continue the resolve.
        next(context);

        // Has an instance been activated?
        if (context.NewInstanceActivated)
        {
            var instanceType = context.Instance.GetType();

            // Get all the injectable properties to set.
            // If you wanted to ensure the properties were only UNSET properties,
            // here's where you'd do it.
            var properties = instanceType
                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Where(p => p.PropertyType == typeof(ILogger) && p.CanWrite && p.GetIndexParameters().Length == 0);

            // Set the properties located.
            foreach (var propToSet in properties)
            {
                propToSet.SetValue(context.Instance, GetLogger(context, instanceType), null);
            }
        }
    }



    /// <summary>
    ///     The log cache.
    /// </summary>
    private static readonly ConcurrentDictionary<Type, object> _logCache = new ConcurrentDictionary<Type, object>();

    /// <summary>
    ///     Gets the logger.
    /// </summary>
    /// <param name="context">The component context.</param>
    /// <param name="declaringType">The type of logger.</param>
    /// <returns>The logger instance.</returns>
    private static object GetGenericTypeLogger(IComponentContext context, Type declaringType)
    {
        return _logCache.GetOrAdd(
            declaringType,
            x =>
            {
                var wrapper = typeof(LoggerWrapper<>);
                var specificWrapper = wrapper.MakeGenericType(declaringType);
                var instance = (ILoggerWrapper)Activator.CreateInstance(specificWrapper);

                var factory = context.Resolve<ILoggerFactory>();

                return instance!.Create(factory);
            });
    }

    /// <summary>
    ///     Gets the logger.
    /// </summary>
    /// <param name="context">The component context.</param>
    /// <param name="declaringType">The type of logger.</param>
    /// <returns>The logger instance.</returns>
    private static object GetLogger(IComponentContext context, Type declaringType)
    {
        return _logCache.GetOrAdd(
            declaringType,
            x =>
            {
                var factory = context.Resolve<ILoggerFactory>();

                return factory.CreateLogger(declaringType);
            });
    }


    /// <summary>
    ///     The <see cref="ILoggerWrapper" />
    ///     interface defines the method for creating a generic type logger.
    /// </summary>
    private interface ILoggerWrapper
    {
        /// <summary>
        ///     Creates a generic type logger using the specified factory.
        /// </summary>
        /// <param name="factory">The factory.</param>
        /// <returns>The logger.</returns>
        object Create(ILoggerFactory factory);
    }

    private class LoggerWrapper<T> : ILoggerWrapper
    {
        public object Create(ILoggerFactory factory)
        {
            return factory.CreateLogger<T>();
        }
    }

}

public class MiddlewareModule : Module
{
    private readonly IResolveMiddleware _middleware;

    public MiddlewareModule(IResolveMiddleware middleware)
    {
        _middleware = middleware;

    }

    protected override void AttachToComponentRegistration(IComponentRegistryBuilder componentRegistry, IComponentRegistration registration)
    {
        // Attach to the registrations pipeline build
        registration.PipelineBuilding += (sender, pipeline) =>
        {
            // Add our middleware to the pipeline
            pipeline.Use(_middleware);

        };
    }
公共类日志中间件:IResolveMiddleware
{
公共PipelinePhase=>PipelinePhase.ParameterSelection;
public void Execute(ResolveRequestContext上下文,下一步操作)
{
var t=context.Registration.Activator.LimitType;
//添加我们的参数。
context.ChangeParameters(context.Parameters.Union(
新[]
{
新的ResolvedParameter((p,i)=>p.ParameterType==typeof(ILogger),(p,i)=>GetLogger(i,t)),
新解析参数(
(p,i)=>p.ParameterType.GenericTypeArguments.Any()&&
p、 ParameterType.GetGenericTypeDefinition()==typeof(ILogger),
(p,i)=>GetGenericTypeLogger(i,t))
}));
//继续下决心。
下一步(上下文);
//实例是否已激活?
if(context.NewInstanceActivated)
{
var instanceType=context.Instance.GetType();
//获取要设置的所有可注入属性。
//如果要确保属性仅为未设置的属性,
//这是你要做的。
var属性=instanceType
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
其中(p=>p.PropertyType==typeof(ILogger)&&p.CanWrite&&p.GetIndexParameters().Length==0);
//设置位于的属性。
foreach(属性中的var propToSet)
{
propToSet.SetValue(context.Instance,GetLogger(context,instanceType),null);
}
}
}
/// 
///日志缓存。
/// 
私有静态只读ConcurrentDictionary _logCache=new ConcurrentDictionary();
/// 
///获取记录器。
/// 
///组件上下文。
///记录器的类型。
///记录器实例。
私有静态对象GetGenericTypeLogger(IComponentContext上下文,类型declaringType)
{
返回_logCache.GetOrAdd(
去极化型,
x=>
{
var wrapper=typeof(LoggerWrapper);
var specificWrapper=wrapper.MakeGenericType(declaringType);
var instance=(ILoggerWrapper)Activator.CreateInstance(specificWrapper);
var factory=context.Resolve();
返回实例!.Create(工厂);
});
}
/// 
///获取记录器。
/// 
///组件上下文。
///记录器的类型。
///记录器实例。
私有静态对象GetLogger(IComponentContext上下文,类型declaringType)
{
返回_logCache.GetOrAdd(
去极化型,
x=>
{
var factory=context.Resolve();
返回工厂。CreateLogger(declaringType);
});
}
/// 
///
///接口定义了创建泛型类型记录器的方法。
/// 
专用接口包装器
{
/// 
///使用指定的工厂创建泛型类型记录器。
/// 
///工厂。
///记录器。
对象创建(iLogger工厂);
}
私有类LoggerWrapper:ILoggerWrapper
{
创建公共对象(iLogger工厂)
{
返回factory.CreateLogger();
}
}
}
公共类MiddlewareModule:模块
{
私有只读中间件\u中间件;
public MiddlewareModule(中间件)
{
_中间件=中间件;
}
受保护的覆盖无效AttachToComponentRegistration(IComponentRegistryBuilder ComponentRegistration,IComponentRegistration注册)
{
//附加到注册管道生成
registration.PipelineBuilding+=(发送方,管道)=>
{
//将我们的中间件添加到管道中
使用(_中间件);
};
}
===============

进一步问题:

所以当我运行这个程序时,我得到了DependencyResolutionException,并且不太确定该去哪里查找

这就是中间件模块注册的样子:


还有其他标准模块执行RegisterType和Register调用。

你说得对;这个示例
MiddlewareModule
在每个注册的管道中注册了
IResolveMiddleware
的一个实例,因此你需要为每个要添加的不同中间件提供一个模块实例


您也可以拥有一个注册多个中间件的自定义模块,或者每次注册都构造一个不同的中间件实例;这只是一个示例。

谢谢@alistair evans,我已经添加到了我的原始帖子中。您知道我收到的dep resolution异常的原因吗?看起来不像是Autofac错误;w我们正在包装一个组件构造函数引发的异常。检查内部异常,看看到底是什么错误。我很难知道如何处理这个异常。我没有直接处理CompiledPageRouteModelProvider,甚至没有真正的sur