You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过反射递归实例化类中的所有嵌套类?

如何通过反射递归实例化类中的所有嵌套类(不修改原类代码)

我需要通过反射自动且递归地实例化某个类中的所有嵌套类,不能修改原类的内部代码,只能从外部处理。我的目标是让这些嵌套类的实例能被序列化器识别,否则序列化器会忽略嵌套类中的常量,只发送外层类的内容。

我已经能通过反射枚举嵌套类型并创建实例,但不知道如何将这些实例附加到外层的容器对象上。

示例模板代码

void someCode()
{
    Nest MyNest = new Nest();
    createInstancesOfAllClassesInside(MyNest);
}

void createInstancesOfAllClassesInside(object anyObj)
{
    // 如何用反射实现?
}

public class Nest
{
    public class A
    {
        public class A1
        {
            public class A2
            {
                public string x = "Activate me!";
            }
        }
    }
    public class B
    {
        public class B1
        {
        }
    }
    public string s = "Hello";
}

补充说明:这里的“激活”就是指用new()实例化嵌套类。

我的非工作尝试

以下是我目前的尝试,但无法实现将实例附加到容器对象的功能:

public void CreateInstancesOfAllClassesInside(object obj)
{
    var objType = obj.GetType();

    // 遍历对象类型的所有嵌套类型
    foreach (Type nestedType in objType.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
    {
        // 创建嵌套类型的实例
        var instance = Activator.CreateInstance(nestedType);

        // 找不到类似SetValue(obj, instance)的方法将实例附加到容器!

        // 递归实例化该实例内部的嵌套类
        CreateInstancesOfAllClassesInside(instance);
    }
}

public void CreateInstancesOfAllClassesInside2(ref object obj)
{
    var objType = obj.GetType();

    // 遍历对象类型的所有嵌套类型
    foreach (Type nestedType in objType.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
    {
        // 创建嵌套类型的实例
        var instance = Activator.CreateInstance(nestedType);

        // 递归实例化该实例内部的嵌套类
        CreateInstancesOfAllClassesInside2(ref instance);

        // 调用构造函数确保初始化
        ConstructorInfo[] ctors = nestedType.GetConstructors();
        if (ctors.Length > 0)
        {
            ctors[0].Invoke(instance, (object[])null);
        }

        // 嵌套类的实例没有出现在根对象中!
    }
}

实际需要处理的类示例

比如下面这个类,实例化_CONST时,内部的FOLDERS_APP、POSTS等嵌套类不会被实例化,导致序列化器忽略其中的常量:

public class _CONST
{
    public class FOLDERS_APP
    {
        public class POSTS
        {
            public const string FOLDER_POSTS_USERS = "somefolder1/";
            public const string FOLDER_PRO_POSTS_FROM_USERS = "somefolder2/";
            public const string FOLDER_FOR_IM_IN_POST = "somefolder3/";
            public const string FOLDER_ATTACH_TO_POSTS = "somefolder4/";
        }
        public class MANIFESTOS
        {
            public const string FOLDER_APPLICATION_MO = "somefolder5/";
            public const string FOLDER_FOM_S = "somefolder6/";
        }
    }
}

解决方案

核心问题在于:原类中并没有定义存储嵌套类实例的字段或属性,所以直接创建嵌套类实例后无法直接附加到原对象上。针对这个问题,有两种可行的处理方式:

方式1:使用ExpandoObject包装原对象(推荐用于序列化场景)

将原对象的成员和嵌套类实例都存入ExpandoObject,这样序列化器可以识别动态添加的嵌套类实例:

public static ExpandoObject WrapWithNestedInstances(object obj)
{
    var expando = new ExpandoObject() as IDictionary<string, object>;

    // 复制原对象的所有公共字段和属性到ExpandoObject
    var objType = obj.GetType();
    foreach (var field in objType.GetFields(BindingFlags.Public | BindingFlags.Instance))
    {
        expando[field.Name] = field.GetValue(obj);
    }
    foreach (var prop in objType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        if (prop.CanRead)
        {
            expando[prop.Name] = prop.GetValue(obj);
        }
    }

    // 递归处理嵌套类型
    foreach (var nestedType in objType.GetNestedTypes(BindingFlags.Public))
    {
        // 创建嵌套类实例
        var nestedInstance = Activator.CreateInstance(nestedType);
        // 递归包装嵌套实例的内部嵌套类
        var wrappedNested = WrapWithNestedInstances(nestedInstance);
        // 将包装后的嵌套实例添加到ExpandoObject中,使用嵌套类的名称作为键
        expando[nestedType.Name] = wrappedNested;
    }

    return (ExpandoObject)expando;
}

使用方式:

void someCode()
{
    _CONST constObj = new _CONST();
    var wrappedObj = WrapWithNestedInstances(constObj);
    // 对wrappedObj进行序列化即可包含所有嵌套类的实例和常量
}

方式2:动态生成派生类并添加嵌套类属性(适合需要强类型的场景)

如果需要强类型的对象,可以通过反射动态生成原类的派生类,自动添加嵌套类的实例属性,再创建该派生类的实例:

using System.Reflection.Emit;

public static object CreateInstanceWithNestedInstances(Type targetType)
{
    // 动态生成派生类
    var assemblyName = new AssemblyName("DynamicNestedInstances");
    var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
    var moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicNestedInstancesModule");
    var typeBuilder = moduleBuilder.DefineType(targetType.Name + "WithNested", TypeAttributes.Public | TypeAttributes.Class, targetType);

    // 为每个嵌套类型添加自动实例化的属性
    foreach (var nestedType in targetType.GetNestedTypes(BindingFlags.Public))
    {
        // 定义私有字段存储嵌套实例
        var fieldBuilder = typeBuilder.DefineField($"_{nestedType.Name}", nestedType, FieldAttributes.Private);
        // 定义公共属性
        var propBuilder = typeBuilder.DefineProperty(nestedType.Name, PropertyAttributes.None, nestedType, null);
        
        // 属性get方法:如果字段未实例化则创建实例并递归处理
        var getMethodBuilder = typeBuilder.DefineMethod($"get_{nestedType.Name}", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, nestedType, Type.EmptyTypes);
        var getIl = getMethodBuilder.GetILGenerator();
        getIl.Emit(OpCodes.Ldarg_0);
        getIl.Emit(OpCodes.Ldfld, fieldBuilder);
        var label = getIl.DefineLabel();
        getIl.Emit(OpCodes.Brtrue_S, label);
        // 创建嵌套实例
        getIl.Emit(OpCodes.Ldarg_0);
        getIl.Emit(OpCodes.Newobj, nestedType.GetConstructor(Type.EmptyTypes));
        // 递归处理嵌套实例的内部嵌套类
        getIl.Emit(OpCodes.Call, typeof(YourClassName).GetMethod("CreateInstanceWithNestedInstances", BindingFlags.Public | BindingFlags.Static));
        getIl.Emit(OpCodes.Stfld, fieldBuilder);
        getIl.MarkLabel(label);
        getIl.Emit(OpCodes.Ldarg_0);
        getIl.Emit(OpCodes.Ldfld, fieldBuilder);
        getIl.Emit(OpCodes.Ret);
        propBuilder.SetGetMethod(getMethodBuilder);
    }

    // 创建动态类型的实例
    var dynamicType = typeBuilder.CreateType();
    return Activator.CreateInstance(dynamicType);
}

使用方式:

void someCode()
{
    var constObj = CreateInstanceWithNestedInstances(typeof(_CONST));
    // constObj包含所有嵌套类的属性,序列化时会包含其中的常量
}

内容的提问来源于stack exchange,提问作者Jada

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 05:44:55