这个问题,对于初学编程的人,可能都会觉得简单,但如前面所说的,简单的东西往往并不简单,为了创建一个对象,就有单独一类的设计模式叫做创建型设计模式。
本文不打算深入设计模式,来看一个创建对象的代码,我觉得写的非常好
using System;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
namespace Orleans.Serialization.Activators
{
//只有在同一程序集的文件中,才能访问内部类型或成员,如以下示例所示:
// new 无参构造函数 这种代码设计主要用于在运行时动态创建泛型类型 T 的实例,并且根据类型是引用类型还是值类型采用不同的实例化策略
internal abstract class DefaultActivator<T> : IActivator<T>
{
private static readonly Func<T> DefaultConstructorFunction = Init();
protected readonly Func<T> Constructor = DefaultConstructorFunction;
protected readonly Type Type = typeof(T);
private static Func<T> Init()
{
var ctor = typeof(T).GetConstructor(Type.EmptyTypes);
if (ctor is null)
return null;
//高效的实例化:通过 DynamicMethod 和 IL 生成(ILGenerator),可以在运行时动态创建一个方法,该方法直接调用类型 T 的无参构造函数。这种方式避免了使用反射调用构造函数时的一些开销,提高了实例化的性能。
var method = new DynamicMethod(nameof(DefaultActivator<T>), typeof(T), new[] { typeof(object) });
var il = method.GetILGenerator();
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Ret);
return (Func<T>)method.CreateDelegate(typeof(Func<T>));
}
public abstract T Create();
}
internal sealed class DefaultReferenceTypeActivator<T> : DefaultActivator<T> where T : class
{
//这里使用了 C# 的模式匹配语法来检查 Constructor 字段是否为非空。如果 Constructor 不为空,则将其赋值给局部变量 ctor,并返回 true;否则返回 false。
public override T Create()
=> Constructor is { } ctor
? ctor()
: Unsafe.As<T>(RuntimeHelpers.GetUninitializedObject(Type));
}
internal sealed class DefaultValueTypeActivator<T> : DefaultActivator<T> where T : struct
{
public override T Create()
=> Constructor is { } ctor
? ctor()
: (T)RuntimeHelpers.GetUninitializedObject(Type);
}
}
Activators的接口定义:
namespace Orleans.Serialization.Activators
{
/// <summary>
/// Functionality for creating object instances.
/// </summary>
/// <typeparam name="T">The instance type which this implementation creates.</typeparam>
public interface IActivator<T>
{
/// <summary>
/// Creates an instance of type <typeparamref name="T"/>.
/// </summary>
/// <returns>An instance of type <typeparamref name="T"/>.</returns>
T Create();
}
}
我写了一个类:
public class SampleClass
{
public SampleClass(int c)
{
Console.WriteLine("SampleClass 实例已创建。");
}
}
class Program
{
static void Main()
{
// 创建引用类型激活器实例
var activator = new DefaultReferenceTypeActivator<SampleClass>();
// 调用 Create 方法创建 SampleClass 实例
SampleClass instance = activator.Create();
// 检查实例是否创建成功
if (instance != null)
{
Console.WriteLine("SampleClass 实例创建成功。");
}
else
{
Console.WriteLine("SampleClass 实例创建失败。");
}
}
}
- 很多人可能会说,我直接new SampleClass()岂不是更简单吗?
是的,但是如果你不知道类型吗?new 什么? 这套代码可以创建任何对象,当然了,这里创建对象使用的是无参数的构造函数。代码中类SampleClass故意设计为带参数的构造函数,旨在说明这种创建对象的方式只能调用无参构造函数
2.为什么不用反射
高效的实例化:通过 DynamicMethod 和 IL 生成(ILGenerator),可以在运行时动态创建一个方法,该方法直接调用类型 T 的无参构造函数。这种方式避免了使用反射调用构造函数时的一些开销,提高了实例化的性能。
- 如果想调用有参数的构造函数怎么写
internal abstract class DefaultActivator<T> : IActivator<T>
{
private readonly Func<object[], T> _constructor; // 改为支持参数的委托
// 构造函数接收参数类型数组
protected DefaultActivator(Type[] parameterTypes)
{
_constructor = CreateConstructor(parameterTypes);
}
private Func<object[], T> CreateConstructor(Type[] parameterTypes)
{
var ctor = typeof(T).GetConstructor(parameterTypes);
if (ctor is null)
return null;
// 动态方法现在接收 object[] 参数
var method = new DynamicMethod(
nameof(DefaultActivator<T>),
typeof(T),
new[] { typeof(object[]) }, // 参数类型为 object[]
true);
var il = method.GetILGenerator();
var paramArray = il.DeclareLocal(typeof(object[]));
// 加载参数数组
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Stloc, paramArray);
// 为每个参数加载并转换类型
for (int i = 0; i < parameterTypes.Length; i++)
{
il.Emit(OpCodes.Ldloc, paramArray);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldelem_Ref);
il.Emit(OpCodes.Unbox_Any, parameterTypes[i]);
}
// 调用构造函数
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Ret);
return (Func<object[], T>)method.CreateDelegate(typeof(Func<object[], T>));
}
public abstract T Create(params object[] args); // 抽象方法支持可变参数
}
// 引用类型激活器
internal sealed class DefaultReferenceTypeActivator<T> : DefaultActivator<T> where T : class
{
public DefaultReferenceTypeActivator(Type[] parameterTypes)
: base(parameterTypes) {}
public override T Create(params object[] args)
=> _constructor is { } ctor
? ctor(args)
: throw new InvalidOperationException($"No constructor found for {typeof(T)}");
}
// 值类型激活器
internal sealed class DefaultValueTypeActivator<T> : DefaultActivator<T> where T : struct
{
public DefaultValueTypeActivator(Type[] parameterTypes)
: base(parameterTypes) {}
public override T Create(params object[] args)
=> _constructor is { } ctor
? ctor(args)
: throw new InvalidOperationException($"No constructor found for {typeof(T)}");
}
调用:
static void Main()
{
// 创建引用类型激活器实例
//var activator = new DefaultReferenceTypeActivator<SampleClass>();
var activator = new DefaultReferenceTypeActivator<SampleClass>(
new[] { typeof(int)});
// 传递参数创建实例
SampleClass instance = activator.Create(123);
/* // 调用 Create 方法创建 SampleClass 实例
SampleClass instance = activator.Create();*/
// 检查实例是否创建成功
if (instance != null)
{
Console.WriteLine("SampleClass 实例创建成功。");
}
else
{
Console.WriteLine("SampleClass 实例创建失败。");
}
}
运行结果:
更多内容,欢迎关注我的微信公众号: 半夏之夜的无情剑客