lundi 4 décembre 2023

C# Merge Null Or Not Existing Properties and its properties from strongly typed Model after deserialization

The problem is I have a config which I can update using my Model, I deploy new update and user won't get updated configuration file, so it will cause null reference exception, etc. Now I just set default values or use new() to make it at least similar to latest configuration value, but its a hell, I need to always support it, what if I'll or someone else even forget to merge null properties?

I have 3 different config files (YAML, XML, JSON),but with single one model. I want it to merge all null properties, arrays of the arrays, not existing items of the array from default config into existing config, properties of the properties, etc, however I want to save all existing things from the deserialized config.

My Model:

[Serializable]
public class GuardSettings
{
    public GuardSettings()
    {
    }

    public UnturnedGuardOptions UnturnedGuardOptions { get; set; }
    public UnturnedIntegrityVault UnturnedIntegrityVault { get; set; }
    public LocalTimeOptions LocalTimeOptions { get; set; }
    [YamlIgnore, XmlIgnore] public VanillaOptions VanillaOptions { get; set; }
    public LogReport LogReport { get; set; }
    public DiscordWebhookLaunch DiscordWebhookLaunch { get; set; }
    public DiscordWebhookReject DiscordWebhookReject { get; set; }
    public DiscordWebhookAccept DiscordWebhookAccept { get; set; }
    public DiscordWebhookCancel DiscordWebhookCancel { get; set; }
    public DiscordWebhookReport DiscordWebhookReport { get; set; }
    public DiscordWebhookBans DiscordWebhookBans { get; set; }
    public DiscordWebhookUnbans DiscordWebhookUnbans { get; set; }
    public DatabaseOptions DatabaseOptions { get; set; }
    public UnturnedPanelIntegration UnturnedPanelIntegration { get; set; }
    public BanOptions BanOptions { get; set; }
    public PlayerWhitelist PlayerWhitelist { get; set; }
    public HWIDHistory HWIDHistory { get; set; }
    [YamlMember(Alias = "tpsOptions")] public TPSOptions TPSOptions { get; set; }
    public FeaturesOptions FeaturesOptions { get; set; }
    public Feature[] Features { get; set; }
}

[Serializable]
public class Feature
{
    public Feature()
    {
    }

    public string Name { get; set; } = string.Empty;
    public bool Enabled { get; set; }
    public Argument[] Arguments { get; set; } = Array.Empty<Argument>();
}

[Serializable]
public class Argument
{
    public Argument()
    {
    }

    public string? Name { get; set; }
    public object? Value { get; set; }
}

This is how I see it, I have default settings just using my custom factory that configures default config with all properties (in a proper way), and the existing settings is a deserialized config from file (YAML, XML or JSON).

private static GuardSettings Merge(GuardSettings defaultSettings, GuardSettings existingSettings)

After that I want to serialize the Merged config to let configuration being updated, so user can change newest properties and be up to date with changes in the config!

I tried to use Reflection and AutoMapper, but with no success.





Aucun commentaire:

Enregistrer un commentaire