gpt4 book ai didi

c# - 在解析期间确定依赖项的目标类型

转载 作者:行者123 更新时间:2023-12-04 11:16:21 28 4
gpt4 key购买 nike

似乎无法确定解析依赖项的类型:

containerBuilder.Register(context =>
{
// What is the type for which this component is resolved?
var type = default(Type); // TBD
return context.Resolve<ILoggerFactory>().CreateLogger(type);
});

此处的目标是创建 .NET Core 记录器,该记录器具有适用于它的类型的正确类别。
Autofac documentation中的例子描述了如何使用中间件组件实现这一点,我成功了。但似乎为每个注册添加一个管道会影响性能,而且我还没有发现一种方法来只将管道应用于依赖 ILogger 的组件的注册。
动机:显而易见的选择似乎是将依赖项更改为 ILogger<T> 类型其中 T 是应用此依赖项的类型,如下所示:
public class Component
{
public Component(ILogger<Component> logger)...
}
但是经验告诉我,很多开发者草草复制粘贴组件,忘记更改类型参数,导致日志困惑。在当前代码中,我们仍然使用 Common.Logging,我们的组件只需要一个非泛型 ILog:
public class Component
{
public Component(ILog log)...
}
在我们之前的 DI 容器 CaSTLe.Windsor 中,它会像这样简单:
public class LoggerSubDependencyResolver : ISubDependencyResolver
{
public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
return dependency.TargetType == typeof(ILog);
}

public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
return CanResolve(context, contextHandlerResolver, model, dependency) ? LogManager.GetLogger(model.Implementation) : null;
}
}
有没有更简单的方法来实现这一点?或者这就是这样做的方法而我过度担心性能影响?

最佳答案

是的,但它没有记录,所以使用它需要您自担风险

containerBuilder.Register(ctx =>
{
var rc = ctx as ResolveRequestContext;
var operation = rc.Operation as IDependencyTrackingResolveOperation;
//this is not going to work for controllers, unless you register them as services
var service = operation.RequestStack.Skip(1).First().Service as TypedService;
return LogManager.GetLogger(service.ServiceType);
});
如果您坚持文档,中间件方法就是这样做的方法。在这种情况下,它几乎是 CaSTLeWindsor 解析器的直接替代品(注意:在 CW 中,每个注册也调用解析器)。并且您可以使用反射仅为依赖 ILog 的类设置中间件。此外,如果性能是一个问题,您可能希望缓存 LogManager.GetLogger 调用,如前所述 in the documentation .
public class Log4NetMiddleware : IResolveMiddleware
{
//Caching LogManager.GetLogger(type)
private ILog _log;

public Log4NetMiddleware(ILog log)
{
_log = log;
}

public PipelinePhase Phase => PipelinePhase.ParameterSelection;

public void Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
{
context.ChangeParameters(context.Parameters.Union(
new[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof(ILog), //This is your CanResolve
(p, i) => _log //Resolve
),
}));

next(context);

//This code below can be removed if you don't need injection via properties
if (context.NewInstanceActivated)
{
var instanceType = context.Instance.GetType();

//This is your CanResolve
var properties = instanceType
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(ILog) && p.CanWrite && p.GetIndexParameters().Length == 0);

foreach (var propToSet in properties)
{
//This is your Resolve
propToSet.SetValue(context.Instance, _log, null);
}
}
}
}
注册看起来像这样
public void ConfigureContainer(ContainerBuilder containerBuilder)
{

containerBuilder.ComponentRegistryBuilder.Registered += (sender, args) =>
{
var type = args.ComponentRegistration
.Activator
.LimitType;

var constructors = type
.GetConstructors(BindingFlags.Instance | BindingFlags.Public);

if (constructors.Any(x => x.GetParameters().Any(p => p.ParameterType == typeof(ILog))))
{
args.ComponentRegistration.PipelineBuilding += (sender2, pipeline) =>
{
pipeline.Use(new Log4NetMiddleware(LogManager.GetLogger(type)));
};
return;
}

//the code below can be removed if you don't inject via properties
var properties = type
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(ILog) && p.CanWrite && p.GetIndexParameters().Length == 0);

if (properties.Any())
{
args.ComponentRegistration.PipelineBuilding += (sender2, pipeline) =>
{
pipeline.Use(new Log4NetMiddleware(LogManager.GetLogger(type)));
};
}
};
}

关于c# - 在解析期间确定依赖项的目标类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67598070/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com