如何创建一个对象

这个问题,对于初学编程的人,可能都会觉得简单,但如前面所说的,简单的东西往往并不简单,为了创建一个对象,就有单独一类的设计模式叫做创建型设计模式。

本文不打算深入设计模式,来看一个创建对象的代码,我觉得写的非常好

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 实例创建失败。");
        }
    }
}
  1. 很多人可能会说,我直接new SampleClass()岂不是更简单吗?

是的,但是如果你不知道类型吗?new 什么? 这套代码可以创建任何对象,当然了,这里创建对象使用的是无参数的构造函数。代码中类SampleClass故意设计为带参数的构造函数,旨在说明这种创建对象的方式只能调用无参构造函数

2.为什么不用反射
高效的实例化:通过 DynamicMethod 和 IL 生成(ILGenerator),可以在运行时动态创建一个方法,该方法直接调用类型 T 的无参构造函数。这种方式避免了使用反射调用构造函数时的一些开销,提高了实例化的性能。

  1. 如果想调用有参数的构造函数怎么写
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 实例创建失败。");
        }
    }

运行结果:
在这里插入图片描述

更多内容,欢迎关注我的微信公众号: 半夏之夜的无情剑客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

helloworddm

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值