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

C#中能否自动生成可触发INotifyPropertyChanged事件的字段/属性Setter?

C#中能否自动生成可触发INotifyPropertyChanged事件的字段/属性Setter?

当然可以!你现在碰到的手动写重复Setter代码的问题,很多C#开发者都深有同感——毕竟每个属性都要写值判断、更新字段、触发事件的逻辑,真的挺繁琐的。结合你提到的SettingEntries类需要触发INotifyPropertyChanged来通知保存设置的场景,给你分享几种实用的自动实现方式:


1. 用基类+CallerMemberName简化重复代码

这是最基础的“半自动”方式,先写一个通用基类封装事件触发逻辑,利用CallerMemberName特性自动获取属性名,避免手动传入字符串:

using System.ComponentModel;
using System.Runtime.CompilerServices;

public class ObservableBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

// 你的SettingEntries类继承这个基类即可
public class SettingEntries : ObservableBase
{
    private string _apiUrl;
    public string ApiUrl
    {
        get => _apiUrl;
        set
        {
            if (_apiUrl != value)
            {
                _apiUrl = value;
                OnPropertyChanged(); // 不需要手动传属性名啦!
            }
        }
    }

    private int _timeout;
    public int Timeout
    {
        get => _timeout;
        set
        {
            if (_timeout != value)
            {
                _timeout = value;
                OnPropertyChanged();
            }
        }
    }
}

这样每个属性的Setter只需要写值判断和调用OnPropertyChanged(),重复代码少了很多。


2. T4模板自动生成属性代码

如果你的属性特别多,还可以用T4模板自动生成完整的属性和Setter逻辑。只需要在模板里定义好字段列表,模板会帮你自动生成包含事件触发的属性代码:

先创建一个.tt文件,写入类似逻辑:

<#@ template language="C#" #>
<#@ output extension=".cs" #>
using System.ComponentModel;
using System.Runtime.CompilerServices;

public class SettingEntries : ObservableBase
{
<#
// 在这里定义你的字段和类型
var properties = new Dictionary<string, string>
{
    {"ApiUrl", "string"},
    {"Timeout", "int"},
    {"MaxRetries", "int"}
};

foreach (var prop in properties)
{
    var fieldName = "_" + prop.Key.ToLower();
#>
    private <#= prop.Value #> <#= fieldName #>;
    public <#= prop.Value #> <#= prop.Key #>
    {
        get => <#= fieldName #>;
        set
        {
            if (<#= fieldName #> != value)
            {
                <#= fieldName #> = value;
                OnPropertyChanged();
            }
        }
    }

<#
}
#>
}

保存后,Visual Studio会自动生成对应的.cs文件,后续添加新字段只需要修改模板里的字典就行,完全不用手动写属性。


3. 用Fody.PropertyChanged实现完全自动

如果你想彻底摆脱手动写Setter的麻烦,可以试试Fody.PropertyChanged这个库——它通过IL织入(IL Weaving)技术,在编译时自动给你的属性添加INotifyPropertyChanged的触发逻辑,你只需要给类加个特性就行:

  1. 先通过NuGet安装PropertyChanged.Fody包
  2. 给你的SettingEntries类添加特性:
using PropertyChanged;

[AddINotifyPropertyChangedInterface]
public class SettingEntries
{
    // 只需要定义自动属性,Fody会自动帮你添加触发逻辑!
    public string ApiUrl { get; set; }
    public int Timeout { get; set; }
    public int MaxRetries { get; set; }
}

编译后,这个类会自动实现INotifyPropertyChanged接口,每个属性的Setter都会自动判断值变化并触发事件,完全不用写任何额外的代码,非常适合你的场景。


这些方法都能帮你自动生成触发INotifyPropertyChanged的Setter,让你的SettingEntries类维护起来更轻松,不用再为每个属性写重复的逻辑啦!

备注:内容来源于stack exchange,提问作者Alaric de Ruiter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:23:10