lundi 13 décembre 2021

Anyway to remove repetition for C# class properties?

I have a class like this:

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();
    }
}

So for every property I need to put the exact name 3 times. I understand this would be bad for maintenance later and prone to mistakes when I make more properties by copying (i.e. forget to replace the name in 1 of the 3 places).

Is there a better way to deal with this? Some solutions came to my mind:

  • Something like the old T4, I don't see the T4 menu anymore in VS2022, so I assume it doesn't work on .NET Core?

  • Code Generator seem to require an external project. I assume this is how EF Core Scaffolding works? Can someone suggest a keyword/link to what I should look for? I.e. read a C# project, look for properties inside a class and generate a .cs file accordingly?


As of current specs, the key text is just the same:

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

So technically I can just replace DbSettingsKeys.EmailApiServer to nameof(EmailApiServer) for example, but I am not sure it will stay the same later. Is it a good idea to proceed with this now and think about it later when specs change?

Update: I just realized that even with nameof(PropertyName), it's still prone to copying issue since there is no error if I forget to change the name:

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

I think something like CallerMemberNameAttribute maybe useful but I don't actually know how it works.

Aucun commentaire:

Enregistrer un commentaire