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

如何使用TypeBuilder/PropertyBuilder定义可空引用类型属性

.NET 6 动态创建类型时标记可空引用类型属性的实现方案

System.Runtime.CompilerServices.NullableAttribute确实没有公开的对外定义,是C#编译器编译时自动内嵌到程序集里的,但运行时完全可以通过反射拿到核心类库中该特性的构造器,直接给动态生成的属性挂载即可,不需要提前引用公开类型。

具体实现步骤

  • 第一步:反射获取NullableAttribute的构造函数
    普通非泛型类型的属性,使用单byte参数的构造函数即可,参数值2代表标记为可空引用类型,1代表非空。
    // 从运行时核心程序集加载特性类型
    var coreAsm = typeof(object).Assembly;
    var nullableAttrType = coreAsm.GetType("System.Runtime.CompilerServices.NullableAttribute")!;
    // 匹配单byte参数的构造器
    var nullableAttrCtor = nullableAttrType.GetConstructor(new[] { typeof(byte) })!;
    
  • 第二步:给PropertyBuilder挂载特性
    按原有逻辑定义属性和get/set访问器后,调用SetCustomAttribute方法挂载构造好的特性即可:
    // 原有属性定义逻辑,示例对应 public MyReferenceType? MyProperty { get; set; }
    PropertyBuilder myProp = typeBuilder.DefineProperty(
        "MyProperty",
        PropertyAttributes.None,
        typeof(MyReferenceType),
        Type.EmptyTypes
    );
    // 定义get、set方法的逻辑按原有业务实现,此处省略
    // myProp.SetGetMethod(...);
    // myProp.SetSetMethod(...);
    
    // 挂载可空标记特性,传byte值2代表该引用类型属性可空
    myProp.SetCustomAttribute(new CustomAttributeBuilder(nullableAttrCtor, new object[] { (byte)2 }));
    

特殊场景说明

  • 如果属性是嵌套泛型类型(比如List<string?>?),需要改用byte[]参数的构造函数,按泛型嵌套层级依次传入对应可空标记值:最外层类型可空传2,内层泛型参数可空也对应位置传2即可。
  • 如果需要给整个动态模块/类型统一开启可空上下文,可以反射获取System.Runtime.CompilerServices.NullableContextAttribute的构造器,给模块、类型级别挂载参数为2的该特性,此时范围内所有引用类型默认视为可空,仅非空属性需要单独标记。
  • 按上述方式生成的类型,可空标记和C#编译器原生生成的?标记效果完全一致,IDE可空分析、运行时反射读取、相关校验逻辑都能正常识别。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 04:33:23