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

C# .NET6中如何编写可在方法前后执行逻辑的Attribute特性

可行实现方案

优先选择和JSON反序列化流程适配的原生方案,不需要额外改造构造逻辑,也不需要外部手动调用初始化方法。

方案1:使用反序列化完成回调(最适配当前需求)

主流.NET JSON序列化库(System.Text.Json、Newtonsoft.Json)都原生支持反序列化生命周期回调,标记对应特性的方法会在「对象构造完成、所有字段/属性赋值完毕」后自动执行,完美避开构造函数内执行初始化时字段还是默认值的问题。
示例代码:

using System.Runtime.Serialization;
// 若使用Newtonsoft.Json,无需额外命名空间,同名特性可直接兼容

public class Spam
{
    public int stored_var = 1;
    private int evaluated_var;

    public Spam() { }
    public Spam(int a)
    {
        this.stored_var = a;
    }

    [OnDeserialized]
    private void AfterObjectCreated(StreamingContext context = default)
    {
        // 此处执行时,无论是反序列化赋值还是构造函数传参赋值都已完成
        this.Initialize();
    }

    public void Initialize()
    {
        this.evaluated_var = this.stored_var + 1;
    }
}

适配说明:

  • 反序列化场景:无参构造执行完、JSON字段全部填充到对象后,会自动触发该方法
  • 手动new对象场景:带参构造中参数赋值完成后,可直接调用该回调方法,逻辑完全内聚在类内部,不需要外部调用者感知

方案2:实现类似Python装饰器的通用构造拦截

如果需要完全不区分创建场景,所有实例(不管是new出来的、反序列化出来的、反射创建的)都自动在构造完成后执行Initialize,可以通过以下两种方式实现你要的[InitializeCaller]特性效果:

  • 编译时代码注入(Source Generator):自定义InitializeCaller特性,编写源生成器在编译阶段扫描所有标记该特性的类,自动生成分部类代码:在所有构造逻辑、字段赋值逻辑执行完成后插入Initialize调用;也可以将构造函数封装为静态工厂方法,在工厂方法中完成「构造实例→赋值→调用Initialize」的全流程,对调用方完全透明。
  • 运行时动态代理:使用动态代理库拦截所有目标类的实例创建过程,在代理逻辑中当构造函数执行完成、实例返回前自动调用Initialize方法。这种方式和Python装饰器的运行时拦截逻辑完全一致,缺点是必须通过代理类创建实例,无法直接new,且不支持密封类。

方案3:值变更触发+延迟初始化(零依赖通用方案)

如果不想依赖任何第三方库或框架特性,可以直接把初始化逻辑和字段访问/赋值绑定,不需要关心对象的创建流程:

public class Spam
{
    private int _stored_var = 1;
    private int _evaluated_var;
    private bool _isInitialized;

    public int stored_var
    {
        get => _stored_var;
        set
        {
            _stored_var = value;
            Initialize();
        }
    }

    public Spam() { }
    public Spam(int a)
    {
        _stored_var = a;
    }

    public int GetEvaluatedValue()
    {
        if (!_isInitialized) Initialize();
        return _evaluated_var;
    }

    public void Initialize()
    {
        _evaluated_var = _stored_var + 1;
        _isInitialized = true;
    }
}

这种方案下,不管对象是通过什么方式创建的:

  • 反序列化时给stored_var赋值会自动触发Initialize
  • 手动new传参赋值后,第一次访问计算值时会自动补做初始化
  • 后续字段值变更时会自动重算依赖值,不会出现数据不一致

注意:C#原生的Attribute仅作为元数据挂载在类型/成员上,本身不具备执行拦截能力,不存在只标记Attribute就自动在构造后执行逻辑的原生实现,必须配合上述的生命周期回调、编译时注入或运行时代理才能生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:30:51