Хотя более зрелые и многофункциональные DI-контейнеры, такие как Autofa c и Simple Injector , поддерживают инъекцию на основе контекста (это функция, которую вы ищете) MS.DI не поддерживает эту функцию.
Именно по этой причине во всей документации Microsoft описывается внедрение обобщенного c ILogger<T>
, где T
равен типу потребления, как в :
public class C
{
public C(ILogger<C> logger) { ... }
}
Разрешение потребителю зависеть от универсального c ILogger<T>
, а не просто зависеть от универсального c ILogger
, однако более многословно и подвержено ошибкам. Это делает ваш код сложнее для тестирования и сложнее поддерживать. Это, вероятно, причина, по которой вы пытаетесь внедрить контекстно-зависимый ILogger
вместо этого, и я приветствую вас за это.
Вы можете «взломать» эту функцию в MS.DI, выполнив итерацию по ServiceCollection
, но есть слишком много ограничений, чтобы это работало в вашем производственном приложении. Однако для развлечения и развлечения вы можете попробовать вот что:
// 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);
}
}
}
Этот код выполняет следующие действия: * ищет регистрации * (закрытого или не универсального c) типа реализации *, который использует Auto-Wiring (то есть без регистрации лямбды или регистрации экземпляров) * и конструктор которой зависит от ILogger
* и заменяет эту регистрацию регистрацией лямбды, которая имеет тип Auto-Wires (с использованием ActivatorUtilities
) при замене зависимости ILogger
с зависимостью ILogger<T>
.
Ограничения:
- Не работает с регистрациями open-generi c
- Не работает с регистрациями делегатов
- Может не работать при замене MS.DI на другие контейнеры DI (например, может «ослепить» контейнер).
- Поведение не определено при работе с несколькими конструкторами
In поэтому я бы не советовал использовать этот подход, а вместо этого использовать зрелый DI-контейнер.
СОВЕТ: Чтобы получить вдохновение, здесь - это простой инжектор описание того, как настроить контейнер для внедрения ASP. NET Core's ILogger
, и базовое c описание того, как применять контекстную инъекцию в Simple Injector, можно найти здесь .