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就交出去。
