无论如何要删除 C# class 属性的重复?

Anyway to remove repetition for C# class properties?

我有一个 class 这样的:

public class DbSettingsValues : Dictionary<string, string>
{

    public DbSettingsValues() { }

    public DbSettingsValues(Dictionary<string, string> values) : base(values) { }

    public string EmailApiServer
    {
        get => this.GetValueOrDefault(DbSettingsKeys.EmailApiServer, "");
        set => this[DbSettingsKeys.EmailApiServer] = value;
    }

    public string EmailApiKey
    {
        get => this.GetValueOrDefault(DbSettingsKeys.EmailApiKey, "");
        set => this[DbSettingsKeys.EmailApiKey] = value;
    }

    // about 15 more...

    // There is also a few difference, like this one:
    public int RegisterFirstEmailDelay
    {
        get => int.Parse(this.GetValueOrDefault(DbSettingsKeys.RegisterFirstEmailDelay, "24"));
        set => this[DbSettingsKeys.RegisterFirstEmailDelay] = value.ToString();
    }
}

所以对于每个 属性 我需要输入准确的名字 3 次。我知道这对以后的维护不利,并且当我通过复制创建更多属性时容易出错(即忘记替换 3 个位置中的 1 个名称)。

有没有更好的方法来处理这个问题?我想到了一些解决方案:


就目前的规格而言,关键文本是一样的:

    public const string EmailApiServer = nameof(EmailApiServer);
    public const string EmailApiKey = nameof(EmailApiKey);
    // ...

所以从技术上讲,我可以将 DbSettingsKeys.EmailApiServer 替换为 nameof(EmailApiServer),但我不确定它以后会保持不变。现在就着手进行,等规格发生变化后再考虑是否是个好主意?

更新:我刚刚意识到即使使用 nameof(PropertyName),它仍然容易出现复制问题,因为如果我忘记更改名称也不会出错:

    // No error here because the name is valid
    public string EmailApiKey
    {
        get => this.GetValueOrDefault(nameof(EmailApiServer), "");
        set => this[nameof(EmailApiServer)] = value;
    }

我认为 CallerMemberNameAttribute 之类的东西可能有用,但实际上我不知道它是如何工作的。

如果键确实与属性同名,您确实可以使用 [CallerMemberName] 属性来减少必须键入 属性 名称的次数。

例如:

public class DbSettingsValues : Dictionary<string, string>
{
    public string EmailApiServer
    {
        get => getProperty();
        set => setProperty(value);
    }

    public string EmailApiKey
    {
        get => getProperty();
        set => setProperty(value);
    }

    public int RegisterFirstEmailDelay
    {
        get => getProperty(24);
        set => setProperty(value);
    }

    string getProperty(string defaultValue = "", [CallerMemberName] string? propName = default)
    {
        return this!.GetValueOrDefault(propName, defaultValue);
    }

    T getProperty<T>(T defaultValue, [CallerMemberName] string? propName = default)
    {
        var result = this!.GetValueOrDefault(propName, defaultValue!.ToString());
        return (T) Convert.ChangeType(result, typeof(T))!;
    }

    void setProperty(string value, [CallerMemberName] string? propName = default)
    {
        this[propName!] = value;
    }

    void setProperty<T>(T value, [CallerMemberName] string? propName = default)
    {
        this[propName!] = value!.ToString()!;
    }
}

它并不完美,但确实显着降低了打字错误的几率。