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

如何使用TypeBuilder生成带属性的C#接口?

动态创建带属性的接口问题解决方法

问题背景

需求是用TypeBuilder动态创建包含属性的接口,目标接口示例如下:

public interface ISample
{
    public decimal Amount { get; set; }
    public decimal Price { get; set; }
    public double Quantity { get; set; }
}

现有代码可编译运行,但生成的接口类型无法识别到任何属性,核心代码如下:

创建TypeBuilder的方法

private static TypeBuilder GetInterfaceTypeBuilder(string TypeName)
{
    var typeSignature = TypeName;
    var an = new AssemblyName(typeSignature);

    AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()),
    AssemblyBuilderAccess.Run);

    ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");

    TypeBuilder tb = moduleBuilder.DefineType(typeSignature, TypeAttributes.Interface | TypeAttributes.Abstract);

    return tb;
}

创建属性的方法

private static void CreateInterfaceProperty(TypeBuilder tb, string propertyName, Type propertyType)
{
    PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
}

编译接口类型的方法

public static Type CompileInterfaceType(string TypeName, List<Field> yourListOfFields)
{
    TypeBuilder tb = GetTypeBuilder(TypeName); // 原代码存在方法名调用错误

    // 假设yourListOfFields包含Field对象,有FieldName(string)和FieldType(Type)属性
    foreach (var field in yourListOfFields)
    {
        CreateInterfaceProperty(tb, field.FieldName, field.FieldType);
    }

    Type objectType = tb.CreateType();
    return objectType;
}

问题原因与解决方法

问题核心在于:接口的属性本质是一对抽象的get/set方法,原代码仅创建了PropertyBuilder,但未定义属性对应的getter和setter方法,导致反射无法识别到属性。

修改后的创建属性方法

private static void CreateInterfaceProperty(TypeBuilder tb, string propertyName, Type propertyType)
{
    // 定义属性
    PropertyBuilder propertyBuilder = tb.DefineProperty(
        propertyName, 
        PropertyAttributes.None, 
        propertyType, 
        null);

    // 定义get方法:public abstract [Type] get_[PropertyName]()
    MethodBuilder getMethodBuilder = tb.DefineMethod(
        $"get_{propertyName}",
        MethodAttributes.Abstract | MethodAttributes.Public | MethodAttributes.Virtual,
        propertyType,
        Type.EmptyTypes);

    // 定义set方法:public abstract void set_[PropertyName]([Type] value)
    MethodBuilder setMethodBuilder = tb.DefineMethod(
        $"set_{propertyName}",
        MethodAttributes.Abstract | MethodAttributes.Public | MethodAttributes.Virtual,
        typeof(void),
        new Type[] { propertyType });

    // 将get/set方法关联到属性
    propertyBuilder.SetGetMethod(getMethodBuilder);
    propertyBuilder.SetSetMethod(setMethodBuilder);
}

修正编译方法的调用错误

public static Type CompileInterfaceType(string TypeName, List<Field> yourListOfFields)
{
    TypeBuilder tb = GetInterfaceTypeBuilder(TypeName);

    foreach (var field in yourListOfFields)
    {
        CreateInterfaceProperty(tb, field.FieldName, field.FieldType);
    }

    return tb.CreateType();
}

关键说明

  • 接口中的属性必须对应抽象的get和set方法,这是.NET接口属性的底层实现逻辑
  • 方法命名必须遵循规范:get_PropertyName和set_PropertyName
  • 方法属性需设置为Abstract | Public | Virtual,符合接口成员的访问规则

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:37:49