【问题标题】:Using ActivatorUtilities.CreateInstance To Create Instance From Type使用 ActivatorUtilities.CreateInstance 从类型创建实例
【发布时间】:2018-10-04 10:30:54
【问题描述】:

我正在尝试使用内置的 .Net 依赖注入重写 .Net Core 中的一些代码。以前,我使用当前代码创建实例(它使用 Unity for DI),效果很好。

var instance = (IPipe)UnityHelper.Container.Resolve(implementation);

对于 .Net Core,我首先尝试了标准 Activator.CreateInstance,它运行良好并创建了我期待的 IPipe 实例。

var instance = (IPipe)Activator.CreateInstance(implementation)

但是。那么问题是,如果实现是在 ctor 中注入服务,那么它们将无法解决(这就是为什么我在上一个项目中使用 Unity.Resolve 来解决这个问题)。

经过一番研究,我发现了 ActivatorUtilities 类,并将其替换为下面的代码(serviceProvider 为 IServiceProvider

var instance = ActivatorUtilities.CreateInstance<IPipe>(serviceProvider, implementation);

但是,我现在收到当前错误。

找不到适合“IPipe”类型的构造函数。确保 类型是具体的,并且为所有参数注册了服务 一个公共构造函数。

我不明白为什么 Activator.CreateInstance 工作正常,但这是在抱怨 IPipe 构造函数?

【问题讨论】:

    标签: c# asp.net-core .net-core asp.net-core-2.0


    【解决方案1】:

    泛型ActivatorUtilities.CreateInstance&lt;T&gt;(IServiceProvider, Object[]) 实际上会创建一个T 类型的实例,并尝试使用服务提供者解析该类型的构造函数参数。您可以传递的对象数组用于附加服务提供者未提供的构造函数参数。

    如果您只想创建运行时类型的实例并让 DI 容器注入依赖项,那么您将需要使用非泛型 ActivatorUtilities.CreateInstance(IServiceProvider, Type, Object[])

    该方法返回一个object,所以如果你想使用它,你必须对它进行类型转换。例如:

    var instance = (IPipe)ActivatorUtilities.CreateInstance(serviceProvider, pipeType);
    

    【讨论】:

    • CreateInstance 的通用和非通用版本是相同的。非通用版本调用通用版本。您使用哪一种取决于您喜欢哪种语法。
    • @Julius 正好相反,泛型调用非泛型,但是是的,它们都做同样的事情。我的观点是,对于 generic 版本(OP 正在使用),参数不是应该创建的实现,而是构造函数参数。由于 OP 想要动态创建实现类型,他们不得不使用非泛型版本。因为如果你有运行时类型引用,你就不能在没有反射的情况下使用泛型方法。
    • 是的,你是对的。很好的更新 - 我不确定你在他们之间有什么不同。
    • 有没有办法将 DI 类型解析和参数化实例激活结合起来?如果没有,我认为这可能是一个有用的功能:stackoverflow.com/q/69207420/1768303
    猜你喜欢
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-03
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多