【问题标题】:How to inject a Type instead of an instance into a constructor using Unity如何使用 Unity 将类型而不是实例注入构造函数
【发布时间】:2017-09-13 22:46:43
【问题描述】:

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

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));

【问题讨论】:

    标签: c# dependency-injection unity-container


    【解决方案1】:

    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

    【讨论】:

    • 如果我使用 RegisterType 执行此操作,则会出现错误:UnitySample.Service 类型没有采用参数 (RuntimeType) 的构造函数。我开始认为如果没有一些包装器或中间工厂这是不可能的,这是一种耻辱。
    • 对不起,我的错!我的原始代码有问题。请忽略。有什么方法可以让工作注册更简单吗?我曾经在 main() container.RegisterType() 中这样注册。所以保持 InjectionConstructor 通用,但连接不同的 IJob 实现?
    • @user183872,你能提供一个完整的(最小的)例子吗?如果它与当前问题不同,我建议您创建另一个。
    • 你是对的。我有几个使用不引用底层服务的公共调度代码的 Windows 服务。我有点喜欢将作业实例连接到 main() 中的类型,而不是每次都指定更复杂的 InjectionConstruction。可能会分裂头发;)
    【解决方案2】:

    是否可以将类型注入构造函数而不是实例?

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

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

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

    或者使用InjectionFactory

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

    【讨论】:

    • 上述情况会导致 Unity 异常(UnitySample.Service 类型没有采用参数 (TheJob) 的构造函数。)
    • @user183872:应该可以。 Read this article 了解相关信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多