C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C# Activator

C#中Activator的具体使用

作者:她说彩礼65万

本文主要介绍了C#中Activator的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Activator 是 C# 中用于动态创建对象实例的核心类,位于 System 命名空间。它通过**反射(Reflection)**机制,在运行时根据类型信息创建对象,而无需在编译时知道具体类型。

🔍 一、Activator的核心作用

🧱 二、常用方法详解

1.Activator.CreateInstance(Type type)

调用类型的无参构造函数创建实例。

Type type = typeof(List<string>);
object instance = Activator.CreateInstance(type);
// 等价于:new List<string>();

✅ 要求:类型必须有 public 无参构造函数,否则抛出 MissingMethodException

2.Activator.CreateInstance(Type type, params object[] args)

调用匹配参数的构造函数创建实例。

Type type = typeof(Dictionary<string, int>);
object dict = Activator.CreateInstance(type, 10); // 调用 Dictionary(int capacity)

🔍 匹配规则

⚠️ 注意:参数必须按构造函数声明顺序传入。

3. 泛型版本:Activator.CreateInstance<T>()

编译时已知类型,但仍用反射创建(性能略低于 new T())。

List<string> list = Activator.CreateInstance<List<string>>();

✅ 要求:T 必须有 public 无参构造函数(受 where T : new() 约束)。

4. 创建非 public 或内部类型(需 BindingFlags)

// 假设 MyClass 有一个 internal 构造函数
Type type = typeof(MyClass);
var instance = Activator.CreateInstance(
    type,
    BindingFlags.NonPublic | BindingFlags.Instance,
    null,
    new object[] { "param" },
    null
);

适用于测试私有构造函数或访问内部类型(需注意安全性)。

5. 创建数组、委托、指针等特殊类型

// 创建长度为 5 的 string 数组
Array arr = (Array)Activator.CreateInstance(typeof(string[]), 5);

// 创建多维数组
Array matrix = Array.CreateInstance(typeof(int), 3, 4); // 更推荐用 Array.CreateInstance

⚙️ 三、底层原理(简要)

Activator.CreateInstance 内部使用:

🚀 四、性能问题与替代方案

❌Activator.CreateInstance性能较差

✅ 高性能替代方案

方案 1:使用System.Linq.Expressions编译表达式树

var constructor = typeof(MyClass).GetConstructor(new Type[] { typeof(string) });
var param = Expression.Parameter(typeof(object[]));
var argsExp = constructor.GetParameters().Select((p, i) =>
    Expression.Convert(Expression.ArrayIndex(param, Expression.Constant(i)), p.ParameterType)
).ToArray();

var newExp = Expression.New(constructor, argsExp);
var lambda = Expression.Lambda<Func<object[], object>>(newExp, param);
var factory = lambda.Compile();

// 使用
object instance = factory(new object[] { "hello" });

方案 2:使用System.Reflection.Emit(更复杂,性能最高)

适用于框架开发(如 DI 容器)。

方案 3:.NET 7+ 推荐:RuntimeHelpers.GetUninitializedObject(仅限无参、跳过构造函数)

object obj = RuntimeHelpers.GetUninitializedObject(typeof(MyClass));
// ⚠️ 危险!不调用构造函数,字段为默认值

方案 4:泛型约束 +new()

public T CreateInstance<T>() where T : new()
{
    return new T(); // 零反射,最快!
}

🛑 五、常见陷阱与注意事项

问题说明
无参构造函数缺失抛出 MissingMethodException
参数类型不匹配抛出 ArgumentException
私有构造函数默认无法调用,需 BindingFlags.NonPublic
值类型处理Activator.CreateInstance(typeof(int)) 返回 0(合法)
抽象类/接口不能直接创建,会抛异常
线程安全CreateInstance 本身线程安全,但创建的对象不一定

✅ 六、典型应用场景

  1. IoC/DI 容器

    object instance = Activator.CreateInstance(implementationType, dependencies);
    
  2. 插件系统(加载外部 DLL)

    Assembly asm = Assembly.LoadFrom("Plugin.dll");
    Type pluginType = asm.GetType("MyPlugin");
    IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
    
  3. ORM 实体实例化
    (如 Entity Framework 动态创建实体对象)

  4. 单元测试中 Mock 对象创建

  5. 泛型工厂模式

    public T Create<T>() => Activator.CreateInstance<T>();
    

📌 总结

特性说明
用途运行时动态创建对象
核心方法CreateInstance(Type, args)
优点灵活,支持任意类型
缺点性能低,易出错
最佳实践仅用于低频场景;高频场景用表达式树或泛型约束

💡 建议:在写 DI 容器、框架或插件系统时,初期可用 Activator 快速验证逻辑,后期替换为高性能方案。

到此这篇关于C#中Activator的具体使用的文章就介绍到这了,更多相关C# Activator内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文