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