使用ActivatorUtilities.CreateInstance从类型创建实例

lee*_*n3o 2 c# .net-core asp.net-core asp.net-core-2.0

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

var instance = (IPipe)UnityHelper.Container.Resolve(implementation);
Run Code Online (Sandbox Code Playgroud)

对于.Net Core,我首先尝试了该标准,Activator.CreateInstance并且效果很好,并创建了我期望的IPipe实例。

var instance = (IPipe)Activator.CreateInstance(implementation)
Run Code Online (Sandbox Code Playgroud)

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

经过研究,我发现了有关ActivatorUtilities该类的信息,并将其替换为下面的代码(serviceProvider是IServiceProvider

var instance = ActivatorUtilities.CreateInstance<IPipe>(serviceProvider, implementation);
Run Code Online (Sandbox Code Playgroud)

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

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

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

pok*_*oke 6

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

如果只想创建运行时类型的实例并让DI容器注入依赖项,则需要使用non-generic ActivatorUtilities.CreateInstance(IServiceProvider, Type, Object[])

该方法返回一个object,因此,如果要使用它,则必须进行类型转换。例如:

var instance = (IPipe)ActivatorUtilities.CreateInstance(serviceProvider, pipeType);
Run Code Online (Sandbox Code Playgroud)

  • @Julius,这是相反的,通用调用非通用,但是,是的,它们都做同样的事情。我的观点是,对于 _generic_ 版本(OP 使用的),参数不是应该创建的实现,而是构造函数参数。由于 OP 想要动态创建实现类型,因此他们必须使用非泛型版本。因为如果有运行时类型引用,则无法在没有反射的情况下使用泛型方法。 (3认同)