在构造函数注入期间,Unity DI 容器能否识别正在构造的类型,并在解析引用时使用它?

During constructor injection can the Unity DI Container recognize the type that is being constructed, and use it when resolving a reference?

我想使用 Unity DI 容器将 Microsoft.Extensions.Logging 记录器注入到 class 的构造函数中:

using Microsoft.Extensions.Logging;

namespace LoggingExample
{    
    public class MyClass
    {
        private readonly ILogger<MyClass> _logger;

        public MyClass(ILogger<MyClass> logger)
        {
            _logger = logger;
        }

        public void DoSomething()
        {
            _logger.LogInformation("Doing something.");
        }
    }
}

Whosebug 回答表明注入 ILogger<T> 不是一个好主意,因为它太具体了。相反,答案建议注入非泛型基类型,ILogger,它更简单、更容易测试并且更不容易出错(我猜主要是复制和粘贴错误)。

在上面的 class 中,我们想要更改构造函数参数的数据类型:

        public MyClass(ILogger logger)
        {
            _logger = logger;
        }

然后我们需要一些方法将 ILogger 解析为 Logger<MyClass> 对于这个 class,或者 Logger<T> 在更一般的情况下对于任何 class,其中 T 代表被注入的 class。

这是在 Whosebug 答案中使用简单注入器 DI 容器和条件注册完成的:

container.RegisterConditional(
    typeof(ILogger),
    c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
    Lifestyle.Singleton,
    _ => true);

Unity 中可以进行条件注册吗? Unity 是否有任何其他方式可以识别 class 它正在注入 ILogger 并解析引用以注入 Logger<T> 对象(其中 T 是 class注入)?

您可以为每个 ILogger 实例定义一个名称,并使用 [Dependency] 属性指定您想要的名称。示例:

public static class Constants
{
    public const string LOGGER_MYCLASS_UNITY_KEY = "ILogger<MyClass>";
}

在您的 Unity 注册中:

IUnityContainer container = new UnityContainer();
container.RegisterType<ILogger, Logger<MyClass>>(Constants.LOGGER_MYCLASS_UNITY_KEY, 
  new ContainerControllerLifetimeManager());

在需要记录器的 class 的构造函数中:

public class MyClass
{
    private readonly ILogger<MyClass> _logger;

    public MyClass([Dependency(Constants.LOGGER_MYCLASS_UNITY_KEY)] ILogger logger)
    {
        _logger = (ILogger<MyClass>)logger;
    }
}

HTH.