我正在使用.net Core2.2并使用依赖注入。我有一些自定义的基础设施依赖项,用于管理日志记录、跟踪等,我将它们注入到类中。我想让依赖项知道它们在哪个类中。如果我像new Logger<Type>();一样实例化这个类,我可以做到这一点,但这可以通过依赖注入来管理吗?
例如:
public class Logger<Type> : ILogger
{
}
public class Foo
{
private Ilogger _logger;
public Foo(ILogger logger)
{
_logger = logger;
}
public void DoStuff()
{
_logger.Log(); //<= knows it's in the Foo class.
}
}我如何将ILogger注入Foo,并让记录器知道它被注入到什么类型?
发布于 2020-03-06 05:17:44
您可以像这样指定类型
public class Foo
{
private Ilogger<Foo> _logger;
}然后在记录器中,您可以通过以下方式了解T的类型
public class Logger<T> : ILogger<T>
{
public Type WhatType() => typeof(T);
}您需要像这样注册服务
serviceCollection.AddSingleton(typeof(ILogger<>), typeof(Logger<>));发布于 2020-03-07 00:36:28
虽然更成熟和功能丰富的DI容器,如Autofac和Simple Injector,确实支持基于上下文的注入(这是您正在寻找的功能),但MS.DI不支持此功能。
正是由于这个原因,所有微软文档都描述了在T等于消费类型的情况下注入通用ILogger<T>,例如:
public class C
{
public C(ILogger<C> logger) { ... }
}然而,让消费者依赖通用ILogger<T>,而不是简单地依赖非通用ILogger,会更加冗长且容易出错。这会让你的代码更难测试,更难维护。这可能是您尝试注入上下文感知ILogger的原因,我为此而鼓掌。
您可以通过迭代ServiceCollection将此功能“黑”到MS.DI中,但实际上它有太多的限制,无法在您的生产应用程序中使用。然而,为了好玩和娱乐,你可以尝试这样做:
// Run just before finalizing the IServiceCollection
for (int i = 0; i < services.Count; i++)
{
ServiceDescriptor descriptor = services[i];
if (descriptor.ImplementationType != null)
{
var loggerParameters =
from ctor in descriptor.ImplementationType.GetConstructors()
from param in ctor.GetParameters()
where param.ParameterType == typeof(ILogger)
select param;
if (loggerParameters.Any())
{
// Replace registration
services[i] =
new ServiceDescriptor(
descriptor.ServiceType,
provider =>
ActivatorUtilities.CreateInstance(
provider,
descriptor.ImplementationType,
provider.GetRequiredService(
typeof(ILogger<>).MakeGenericType(
descriptor.ImplementationType))),
descriptor.Lifetime);
}
}
}这段代码的作用是:
ILogger的实例registration)
ActivatorUtilities),同时将ILogger依赖项替换为ILogger<T>依赖项。限制:
当用另一个DI容器替换registrations
因此,在实践中,我不建议使用这种方法,而是使用成熟的DI Container。
提示:为了获得一些灵感,在使用Simple Injector时,可以按如下方式进行基于上下文的注册:
container.RegisterConditional(
typeof(ILogger),
c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);当与ASP.NET核心集成时,简单注入器甚至包含一个扩展方法来简化这一点。Here关于如何配置容器以注入ASP.NET核心的ILogger的简单注入器文档,以及关于如何在简单注入器中应用基于上下文的注入的基本描述可以在here中找到。
https://stackoverflow.com/questions/60553855
复制相似问题