如何使用 Unity 将类型而不是实例注入构造函数

How to inject a Type instead of an instance into a constructor using Unity

是否可以将类型而不是实例注入到构造函数中? 如果是这样,这是如何实现的?如果可能,我想避免显式注册工厂方法或就地解析实例。

public interface IJob { }
public class TheJob : IJob { }

public interface IService
{
    string GetTypeDesc();
}

public class Service : IService
{
    private Type _jobType;

    public Service(Type jobType)
    {
        _jobType = jobType;
    }

    public string GetTypeDesc()
    {
        return _jobType.ToString();
    }
}

似乎即使在使用显式构造函数定义注册类型时,Unity 也想将一个实例注入到类型占位符中。

Type jobType = typeof(TheJob);    
(new UnityContainer()).RegisterType<IService, Service>(new InjectionConstructor(jobType));

Is it possible to inject a type into a constructor instead of an instance?

A System.Type 是一种二义性类型,就像 System.StringSystem.Int32 等基本类型一样。它们被认为是不明确的,因为在运行时该类型有多个(或许多)可能的值。这可以防止 DI 容器自动为您解析和注入此类值的实例。

这意味着您应该手动将值提供给 Unity。这可以使用 InjectionConstructor 来完成(正如您已经在做的那样):

.RegisterType<IService, Service>(new InjectionConstructor(jobType))

或使用 InjectionFactory:

.Register<IService>(new InjectionFactory(c => new Service(jobType)))

InjectionConstructor 的构造函数接受一个对象数组。如果传递给 InjectionConstructor 的构造函数(在数组中)的对象类型是 Type 类型,unity 将尝试解析该类型,然后将结果传递给构造函数('Service`例如)。

例如,如果您使用 new InjectionConstructor(typeof(IMyOtherService)),那么 unity 将期望 Service 的构造函数采用类型 IMyOtherService 的实例,并将使用容器来解析此类。换句话说,Type 是一种特殊情况,您需要以特定方式处理。

要解决您的问题,您应该告诉 Unity 您传递的 Type 实际上是一个构造函数参数。你可以这样做:

new InjectionConstructor(new InjectionParameter(jobType))

这会强制 unity 将 jobType 视为构造函数参数。

有关详细信息,请参阅此处的 InjectionParameterValue.ToParameter 方法:https://github.com/unitycontainer/unity/blob/master/source/Src/Unity-CoreClr/Injection/InjectionParameterValue.cs