C#中Activator的具体使用
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>🔍 一、Activator的核心作用</li><li>🧱 二、常用方法详解</li><ul class="second_class_ul"><li>1.Activator.CreateInstance(Type type)</li><li>2.Activator.CreateInstance(Type type, params object[] args)</li><li>3. 泛型版本:Activator.CreateInstance<T>()</li><li>4. 创建非 public 或内部类型(需 BindingFlags)</li><li>5. 创建数组、委托、指针等特殊类型</li></ul><li>⚙️ 三、底层原理(简要)</li><ul class="second_class_ul"></ul><li>🚀 四、性能问题与替代方案</li><ul class="second_class_ul"><li>❌Activator.CreateInstance性能较差</li><li>✅ 高性能替代方案</li><ul class="third_class_ul"><li>方案 1:使用System.Linq.Expressions编译表达式树</li><li>方案 2:使用System.Reflection.Emit(更复杂,性能最高)</li><li>方案 3:.NET 7+ 推荐:RuntimeHelpers.GetUninitializedObject(仅限无参、跳过构造函数)</li><li>方案 4:泛型约束 +new()</li></ul></ul><li>🛑 五、常见陷阱与注意事项</li><ul class="second_class_ul"></ul><li>✅ 六、典型应用场景</li><ul class="second_class_ul"></ul><li>📌 总结</li><ul class="second_class_ul"></ul></ul></div><p><code>Activator</code> 是 C# 中用于<strong>动态创建对象实例</strong>的核心类,位于 <code>System</code> 命名空间。它通过**反射(Reflection)**机制,在运行时根据类型信息创建对象,而无需在编译时知道具体类型。</p><p class="maodian"></p><h2>🔍 一、Activator的核心作用</h2>
<ul><li>在<strong>不知道具体类型</strong>的情况下创建实例(如 IoC 容器、插件系统、序列化框架等)。</li><li>支持<strong>带参数</strong>或<strong>无参</strong>的构造函数调用。</li><li>可创建<strong>值类型</strong>和<strong>引用类型</strong>。</li><li>是依赖注入(DI)、ORM、MVC 框架等底层常用工具。</li></ul>
<p class="maodian"></p><h2>🧱 二、常用方法详解</h2>
<p class="maodian"></p><h3>1.Activator.CreateInstance(Type type)</h3>
<blockquote><p>调用类型的<strong>无参构造函数</strong>创建实例。</p></blockquote>
<div class="jb51code"><pre class="brush:csharp;">Type type = typeof(List<string>);
object instance = Activator.CreateInstance(type);
// 等价于:new List<string>();
</pre></div>
<p>✅ 要求:类型必须有 <strong>public 无参构造函数</strong>,否则抛出 <code>MissingMethodException</code>。</p>
<p class="maodian"></p><h3>2.Activator.CreateInstance(Type type, params object[] args)</h3>
<blockquote><p>调用<strong>匹配参数的构造函数</strong>创建实例。</p></blockquote>
<div class="jb51code"><pre class="brush:csharp;">Type type = typeof(Dictionary<string, int>);
object dict = Activator.CreateInstance(type, 10); // 调用 Dictionary(int capacity)
</pre></div>
<p>🔍 <strong>匹配规则</strong>:</p>
<ul><li>按参数数量和类型<strong>精确匹配</strong>(不支持隐式转换,如 <code>int</code> → <code>long</code> 会失败)。</li><li>如果多个构造函数匹配,行为<strong>未定义</strong>(通常选第一个,但不可靠)。</li></ul>
<p>⚠️ 注意:参数必须按构造函数声明顺序传入。</p>
<p class="maodian"></p><h3>3. 泛型版本:Activator.CreateInstance<T>()</h3>
<p>编译时已知类型,但仍用反射创建(性能略低于 new T())。</p>
<div class="jb51code"><pre class="brush:csharp;">List<string> list = Activator.CreateInstance<List<string>>();
</pre></div>
<p>✅ 要求:<code>T</code> 必须有 <strong>public 无参构造函数</strong>(受 <code>where T : new()</code> 约束)。</p>
<p class="maodian"></p><h3>4. 创建非 public 或内部类型(需 BindingFlags)</h3>
<div class="jb51code"><pre class="brush:csharp;">// 假设 MyClass 有一个 internal 构造函数
Type type = typeof(MyClass);
var instance = Activator.CreateInstance(
type,
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new object[] { "param" },
null
);
</pre></div>
<blockquote><p>适用于测试私有构造函数或访问内部类型(需注意安全性)。</p></blockquote>
<p class="maodian"></p><h3>5. 创建数组、委托、指针等特殊类型</h3>
<div class="jb51code"><pre class="brush:csharp;">// 创建长度为 5 的 string 数组
Array arr = (Array)Activator.CreateInstance(typeof(string[]), 5);
// 创建多维数组
Array matrix = Array.CreateInstance(typeof(int), 3, 4); // 更推荐用 Array.CreateInstance
</pre></div>
<p class="maodian"></p><h2>⚙️ 三、底层原理(简要)</h2>
<p><code>Activator.CreateInstance</code> 内部使用:</p>
<ul><li><strong>反射</strong>(<code>ConstructorInfo.Invoke</code>)</li><li>在 .NET Core / .NET 5+ 中,对常见场景做了<strong>优化</strong>(如缓存委托)</li><li>但仍比 <code>new</code> 慢 <strong>10~100 倍</strong>(见下文性能)</li></ul>
<p class="maodian"></p><h2>🚀 四、性能问题与替代方案</h2>
<p class="maodian"></p><h3>❌Activator.CreateInstance性能较差</h3>
<ul><li>每次调用都涉及反射、参数校验、安全检查。</li><li>不适合高频调用(如循环内)。</li></ul>
<p class="maodian"></p><h3>✅ 高性能替代方案</h3>
<p class="maodian"></p><h4>方案 1:使用System.Linq.Expressions编译表达式树</h4>
<div class="jb51code"><pre class="brush:csharp;">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" });
</pre></div>
<p class="maodian"></p><h4>方案 2:使用System.Reflection.Emit(更复杂,性能最高)</h4>
<blockquote><p>适用于框架开发(如 DI 容器)。</p></blockquote>
<p class="maodian"></p><h4>方案 3:.NET 7+ 推荐:RuntimeHelpers.GetUninitializedObject(仅限无参、跳过构造函数)</h4>
<div class="jb51code"><pre class="brush:csharp;">object obj = RuntimeHelpers.GetUninitializedObject(typeof(MyClass));
// ⚠️ 危险!不调用构造函数,字段为默认值
</pre></div>
<p class="maodian"></p><h4>方案 4:泛型约束 +new()</h4>
<div class="jb51code"><pre class="brush:csharp;">public T CreateInstance<T>() where T : new()
{
return new T(); // 零反射,最快!
}
</pre></div>
<p class="maodian"></p><h2>🛑 五、常见陷阱与注意事项</h2>
<table><thead><tr><th>问题</th><th>说明</th></tr></thead><tbody><tr><td>无参构造函数缺失</td><td>抛出 MissingMethodException</td></tr><tr><td>参数类型不匹配</td><td>抛出 ArgumentException</td></tr><tr><td>私有构造函数</td><td>默认无法调用,需 BindingFlags.NonPublic</td></tr><tr><td>值类型处理</td><td>Activator.CreateInstance(typeof(int)) 返回 0(合法)</td></tr><tr><td>抽象类/接口</td><td>不能直接创建,会抛异常</td></tr><tr><td>线程安全</td><td>CreateInstance 本身线程安全,但创建的对象不一定</td></tr></tbody></table>
<p class="maodian"></p><h2>✅ 六、典型应用场景</h2>
<ol><li><p><strong>IoC/DI 容器</strong></p>
<div class="jb51code"><pre class="brush:csharp;">object instance = Activator.CreateInstance(implementationType, dependencies);
</pre></div></li><li><p><strong>插件系统(加载外部 DLL)</strong></p>
<div class="jb51code"><pre class="brush:csharp;">Assembly asm = Assembly.LoadFrom("Plugin.dll");
Type pluginType = asm.GetType("MyPlugin");
IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
</pre></div></li><li><p><strong>ORM 实体实例化</strong><br />(如 Entity Framework 动态创建实体对象)</p></li><li><p><strong>单元测试中 Mock 对象创建</strong></p></li><li><p><strong>泛型工厂模式</strong></p>
<div class="jb51code"><pre class="brush:csharp;">public T Create<T>() => Activator.CreateInstance<T>();
</pre></div></li></ol>
<p class="maodian"></p><h2>📌 总结</h2>
<table><thead><tr><th>特性</th><th>说明</th></tr></thead><tbody><tr><td>用途</td><td>运行时动态创建对象</td></tr><tr><td>核心方法</td><td>CreateInstance(Type, args)</td></tr><tr><td>优点</td><td>灵活,支持任意类型</td></tr><tr><td>缺点</td><td>性能低,易出错</td></tr><tr><td>最佳实践</td><td>仅用于低频场景;高频场景用表达式树或泛型约束</td></tr></tbody></table>
<blockquote><p>💡 建议:在写 DI 容器、框架或插件系统时,初期可用 Activator 快速验证逻辑,后期替换为高性能方案。</p></blockquote>
<p>到此这篇关于C#中Activator的具体使用的文章就介绍到这了,更多相关C# Activator内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
<div class="art_xg">
<b>您可能感兴趣的文章:</b><ul><li>C#中Activator.CreateInstance()方法用法分析</li></ul>
</div>
</div>
<!--endmain-->
頁:
[1]