[英]Is it possible to get the requesting service type at resolution time in Autofac?
I'm using Serilog and Autofac and I would like to register an ILogger
using .ForContext()
at resolution time with the type of the object to be injected with the ILogger
.我正在使用Serilog和Autofac ,我想在解析时使用
.ForContext()
注册一个ILogger
,并使用ILogger
注入的对象类型。 Using the debugger, I can walk the IComponentContext
and see what I want but the types to get to it are all internal so I can't (as far as I'm aware) actually get to it in my code.使用调试器,我可以遍历
IComponentContext
并查看我想要的内容,但是获取它的类型都是内部的,所以我不能(据我所知)实际上在我的代码中得到它。 My registration code (which doesn't work as stated above) looks like this:我的注册码(如上所述不起作用)如下所示:
builder.RegisterType<SerilogLoggerFactory>().As<ISerilogLoggerFactory>().SingleInstance();
builder.Register(context =>
{
var defaultResolveRequestContext = (Autofac.Core.Resolving.Pipeline.DefaultResolveRequestContext)context;
var resolveOperation = (Autofac.Core.Resolving.ResolveOperation)defaultResolveRequestContext.Operation;
var initiatingRequestService = (Autofac.Core.TypedService)resolveOperation.InitiatingRequest.Service;
return context.Resolve<ISerilogLoggerFactory>().Create().ForContext(initiatingRequestService.ServiceType);
});
DefaultResolveRequestContext
, ResolveOperation
, and InitiatingRequest
are all inaccessible due to their protection level. DefaultResolveRequestContext
、 ResolveOperation
和InitiatingRequest
都因为它们的保护级别而无法访问。
Any thoughts or ideas would be appreciated.任何想法或想法将不胜感激。
Given the goal is to inject the right ILogger
for a given requesting type, you may want to look at the log4net example in the documentation and adapt it.鉴于目标是为给定的请求类型注入正确的
ILogger
,您可能需要查看 文档中的 log4net 示例并对其进行调整。 Basically, rather than trying to register the ILogger
, it adds the appropriate parameter to the resolve chain so it'll be set up correctly.基本上,它不是尝试注册
ILogger
,而是将适当的参数添加到解析链中,以便正确设置。
Thanks to @Travis Illig's response , we created the following implementation:感谢@Travis Illig 的回复,我们创建了以下实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Autofac.Core;
using Autofac.Core.Resolving.Pipeline;
using Serilog;
namespace YOUR_COMPANY_NAME.Core.Logging.Serilog;
/// <summary>
/// Injects resolved types with <see cref="ILogger.ForContext(Type)"/> for <see cref="ILogger"/>.
/// Supports both constructor and property injection.
/// Inspired by <see href="link">https://autofac.readthedocs.io/en/latest/examples/log4net.html</see>.
/// </summary>
public class AutofacSerilogMiddleware : IResolveMiddleware
{
private readonly ILogger _rootLogger;
private readonly Dictionary<Type, List<PropertyInfo>> _loggerPropertiesCache = new();
public PipelinePhase Phase => PipelinePhase.ParameterSelection;
public AutofacSerilogMiddleware(ILogger rootLogger)
{
_rootLogger = rootLogger;
}
public void Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
{
context.ChangeParameters(context.Parameters.Union(new[] { new ResolvedParameter((p, i) => p.ParameterType == typeof(ILogger), (p, i) => p.Member.DeclaringType != null ? _rootLogger.ForContext(p.Member.DeclaringType) : _rootLogger), }));
// Continue the resolve.
next(context);
// Has an instance been activated?
if (!context.NewInstanceActivated || context.Instance == null)
{
return;
}
var instanceType = context.Instance.GetType();
if (!_loggerPropertiesCache.TryGetValue(instanceType, out var propertyInfos))
{
// Get all the injectable properties to set.
propertyInfos = instanceType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.PropertyType == typeof(ILogger) && p.CanWrite && p.GetIndexParameters().Length == 0).ToList();
_loggerPropertiesCache[instanceType] = propertyInfos;
}
if (!propertyInfos.Any())
{
return;
}
var contextLogger = _rootLogger.ForContext(instanceType);
foreach (var propertyInfo in propertyInfos)
{
//Performance could be improved by generating and caching setter delegates instead of using PropertyInfo.SetValue
propertyInfo.SetValue(context.Instance, contextLogger, null);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.