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

.NET Core7中如何用AssemblyBuilder和TypeBuilder定义List<Foo>属性

解决方案

你的AddProperty方法核心逻辑本身是正确的,但使用时出现报错大概率是两个原因:一是动态生成的List字段未初始化导致空引用异常,二是如果Foo也是动态生成的类型,未确保其在创建泛型List类型前已完成类型构建。以下是修正后的完整实现方案:

1. 优化AddProperty方法

移除冗余指令,保留核心逻辑:

public static void AddProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType)
{
    var fieldBuilder = typeBuilder.DefineField($"_{propertyName}", propertyType, FieldAttributes.Private);
    var propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);

    // Get方法实现
    var getMethod = typeBuilder.DefineMethod($"get_{propertyName}",
        MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
        propertyType, Type.EmptyTypes);
    var getIL = getMethod.GetILGenerator();
    getIL.Emit(OpCodes.Ldarg_0);
    getIL.Emit(OpCodes.Ldfld, fieldBuilder);
    getIL.Emit(OpCodes.Ret);

    // Set方法实现
    var setMethod = typeBuilder.DefineMethod($"set_{propertyName}",
        MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
        null, new[] { propertyType });
    var setIL = setMethod.GetILGenerator();
    setIL.Emit(OpCodes.Ldarg_0);
    setIL.Emit(OpCodes.Ldarg_1);
    setIL.Emit(OpCodes.Stfld, fieldBuilder);
    setIL.Emit(OpCodes.Ret);

    propertyBuilder.SetGetMethod(getMethod);
    propertyBuilder.SetSetMethod(setMethod);
}

2. 关键:为List字段添加初始化逻辑

动态类的字段默认值为null,直接调用List属性会触发空引用异常,需在无参构造函数中初始化List:

public static void AddListInitializer(TypeBuilder typeBuilder, FieldBuilder listField)
{
    var listCtor = listField.FieldType.GetConstructor(Type.EmptyTypes);
    if (listCtor == null)
        throw new InvalidOperationException("List类型无可用的无参构造函数");

    // 定义无参构造函数
    var ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
    var ctorIL = ctor.GetILGenerator();

    // 调用基类构造函数
    ctorIL.Emit(OpCodes.Ldarg_0);
    ctorIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));

    // 初始化List字段
    ctorIL.Emit(OpCodes.Ldarg_0);
    ctorIL.Emit(OpCodes.Newobj, listCtor);
    ctorIL.Emit(OpCodes.Stfld, listField);

    ctorIL.Emit(OpCodes.Ret);
}

3. 完整的动态程序集生成流程

示例1:生成带List属性的类型

// 定义程序集和模块
var assemblyName = new AssemblyName("DynamicListAssembly");
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, $"{assemblyName.Name}.dll");

// 定义动态类型
var typeBuilder = moduleBuilder.DefineType("DynamicType", TypeAttributes.Public | TypeAttributes.Class);

// 添加List<string>属性
var listStringType = typeof(List<string>);
AddProperty(typeBuilder, "Items", listStringType);

// 获取字段并添加初始化逻辑
var fieldBuilder = typeBuilder.GetField("_Items", BindingFlags.NonPublic | BindingFlags.Instance);
AddListInitializer(typeBuilder, fieldBuilder);

// 完成类型创建并保存程序集
var dynamicType = typeBuilder.CreateType();
assemblyBuilder.Save($"{assemblyName.Name}.dll");

示例2:生成带自定义Foo类型的List属性(Foo为动态生成)

// 先创建自定义Foo类型
var fooTypeBuilder = moduleBuilder.DefineType("Foo", TypeAttributes.Public | TypeAttributes.Class);
AddProperty(fooTypeBuilder, "Id", typeof(int));
AddProperty(fooTypeBuilder, "Name", typeof(string));
var fooType = fooTypeBuilder.CreateType();

// 构造List<Foo>泛型类型
var listFooType = typeof(List<>).MakeGenericType(fooType);

// 添加List<Foo>属性到DynamicType
AddProperty(typeBuilder, "FooItems", listFooType);
var fooFieldBuilder = typeBuilder.GetField("_FooItems", BindingFlags.NonPublic | BindingFlags.Instance);
AddListInitializer(typeBuilder, fooFieldBuilder);

// 完成类型创建并保存
var dynamicType = typeBuilder.CreateType();
assemblyBuilder.Save($"{assemblyName.Name}.dll");

测试生成的程序集

// 加载程序集
var assembly = Assembly.LoadFrom("DynamicListAssembly.dll");
var dynamicType = assembly.GetType("DynamicType");

// 创建实例并使用属性
var instance = Activator.CreateInstance(dynamicType);
var itemsProperty = dynamicType.GetProperty("Items");
var items = (List<string>)itemsProperty.GetValue(instance);
items.Add("Test Item");
Console.WriteLine(items.Count); // 输出1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 12:35:27