C# 反射创建实例方法 C#如何使用Activator.CreateInstance

来源:这里教程网 时间:2026-02-21 17:39:37 作者:

Activator.CreateInstance 为什么有时抛出 MissingMethodException

因为

Activator.CreateInstance
默认只找无参构造函数。如果目标类型没有 public 无参构造,或者你传了参数但类型不匹配、顺序不对,就会直接报
MissingMethodException

常见踩坑点:

类写了带参构造,又没显式声明无参构造 → 编译器不会自动补,反射就找不到 传入参数是
int
,但构造函数参数是
long
object
→ 不会自动装箱或隐式转换,必须类型严格一致
泛型类型未闭合(比如
typeof(List)
)→ 必须用
MakeGenericType
先构造具体类型

创建带参实例的正确写法

必须显式指定参数类型数组和参数值数组,二者顺序、数量、类型要完全对应。

var type = typeof(MyClass);
var args = new object[] { "hello", 42 };
var argTypes = new Type[] { typeof(string), typeof(int) };
var instance = Activator.CreateInstance(type, argTypes, args);

更安全的做法是先检查构造函数是否存在:

type.GetConstructors()
查看可用构造器
对每个
ConstructorInfo
调用
GetParameters()
确认参数签名
避免硬编码索引,优先按参数名或类型匹配,而非位置

泛型类型怎么用 CreateInstance

不能直接对开放泛型(如

List<t></t>
)调用
CreateInstance
,必须先构造闭合类型。

var openType = typeof(List<>);
var closedType = openType.MakeGenericType(typeof(string));
var list = Activator.CreateInstance(closedType); // 返回 object,需 cast

注意:

MakeGenericType
抛异常很常见:传入
null
、类型数不匹配、泛型约束不满足都会失败
返回值是
object
,若需强类型操作,得用
as IList<string></string>
(IList<string>)list</string>
,后者可能抛
InvalidCastException

性能差在哪?有没有替代方案

Activator.CreateInstance
每次调用都走完整反射流程,包括构造函数查找、参数验证、JIT 编译委托 —— 在高频场景(如对象池、序列化循环)中开销明显。

更高效的方式:

缓存
ConstructorInfo
,再用
ConstructorInfo.Invoke()
(仍慢,但省去查找)
Expression.Lambda
编译一次构造委托,后续直接调用(推荐)
.NET 5+ 可考虑
System.Runtime.CompilerServices.Unsafe
Unsafe.As<t>(null)</t>
配合字段初始化(仅限无构造逻辑的 POD 类型)

真正复杂的是带依赖注入或生命周期管理的场景 —— 这时候别硬刚

Activator
,该交出去给
IServiceProvider
就交出去。

相关推荐