17370845950

C# 反射创建实例方法 C#如何使用Activator.CreateInstance
Activator.CreateInstance 抛出 MissingMethodException 是因为默认只查找 public 无参构造函数;若类型无该构造、参数类型/顺序不匹配、或泛型未闭合,均会触发此异常。

Activator.CreateInstance 为什么有时抛出 MissingMethodException

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

常见踩坑点:

  • 类写了带参构造,又没显式声明无参构造 → 编译器不会自动补,反射就找不到
  • 传入参数是 int,但构造函数参数是 longobject → 不会自动装箱或隐式转换,必须类型严格一致
  • 泛型类型未闭合(比如 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)调用 CreateInstance,必须先构造闭合类型。

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

注意:

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

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

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

更高效的方式:

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

真正复杂的是带依赖注入或生命周期管理的场景 —— 这时候别硬刚 Activator,该交出去给 IServi

ceProvider 就交出去。