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

C#自定义单例Settings类嵌套成员访问及层级分组实现咨询

自定义C#设置类的正确实现方案

核心问题解答

你要实现的单例+分组访问+序列化需求,嵌套类+实例化分组属性是完全合理的方案(并非唯一方式,但在分组语义上最清晰)。你之前的第二种写法方向正确,只需优化命名、完善初始化逻辑,同时处理好多层嵌套和动态表的场景即可。

基础实现:分组访问的标准写法

无需给嵌套类加下划线前缀,用清晰命名即可,同时在MQSettings构造函数中初始化所有分组对象,避免空引用:

internal class MQSettings : BaseClasses.SaveableObject
{
    public override string Filepath => StaticSettings.MQSettingsPath;

    // 基础配置项,初始化默认空集合
    internal List<string> MandatoryFolders { get; set; } = new();
    internal List<string> MandatoryTables { get; set; } = new();

    // 分组属性
    internal Foldernames Foldernames { get; set; }
    internal Tablenames Tablenames { get; set; }

    // 构造函数:初始化分组对象+默认值
    public MQSettings()
    {
        Foldernames = new Foldernames();
        Tablenames = new Tablenames();
        
        // 设置默认值
        Foldernames.Config = "Configs";
        Foldernames.Backups = "Backups";
        Tablenames.User = "Users";
        Tablenames.Members = "Members";
    }

    // 分组嵌套类
    internal class Foldernames
    {
        internal string Config { get; set; }
        internal string Backups { get; set; }
        // 更多路径配置
    }

    internal class Tablenames
    {
        internal string Members { get; set; }
        internal string User { get; set; }
        // 更多表名配置
    }
}

这样就能按你想要的方式访问:

string configFolder = LoadedData.Settings.Foldernames.Config;
string userTable = LoadedData.Settings.Tablenames.User;

多层嵌套的实现(如数据库字段)

对于Database.Fieldnames.UserTable.ID这类多层分组,直接延续嵌套类逻辑,确保每层对象都被初始化:

internal class MQSettings : BaseClasses.SaveableObject
{
    public override string Filepath => StaticSettings.MQSettingsPath;

    internal Foldernames Foldernames { get; set; }
    internal DatabaseSettings Database { get; set; }

    public MQSettings()
    {
        Foldernames = new Foldernames();
        Database = new DatabaseSettings();
        
        // 初始化默认值
        Database.Credentials = new AppName.DataTypes.Database.Credentials();
        Database.Fieldnames.UserTable.ID = "user_id";
        Database.Fieldnames.UserTable.Name = "user_name";
    }

    internal class Foldernames
    {
        internal string Config { get; set; }
        internal string Templates { get; set; }
        internal string Backups { get; set; }
    }

    internal class DatabaseSettings
    {
        internal AppName.DataTypes.Database.Credentials? Credentials { get; set; }
        internal FieldNames Fieldnames { get; set; }

        public DatabaseSettings()
        {
            Fieldnames = new FieldNames();
        }

        internal class FieldNames
        {
            internal UserTableFieldNames UserTable { get; set; }
            internal MemberTableFieldNames MemberTable { get; set; }

            public FieldNames()
            {
                UserTable = new UserTableFieldNames();
                MemberTable = new MemberTableFieldNames();
            }

            internal class UserTableFieldNames
            {
                internal string ID { get; set; }
                internal string Name { get; set; }
            }

            internal class MemberTableFieldNames
            {
                internal string ID { get; set; }
                internal string Email { get; set; }
            }
        }
    }
}

访问方式:

string userIdColumn = LoadedData.Settings.Database.Fieldnames.UserTable.ID;

动态表的处理(支持新增表的字段配置)

如果要支持运行时创建的新表,不能用固定嵌套类,改用Dictionary<string, TableFieldConfig>存储动态表配置,同时保留固定表的嵌套类方便访问:

internal class MQSettings : BaseClasses.SaveableObject
{
    public override string Filepath => StaticSettings.MQSettingsPath;

    internal DatabaseSettings Database { get; set; }

    public MQSettings()
    {
        Database = new DatabaseSettings();
        // 初始化固定表默认值
        Database.FixedFieldNames.UserTable.ID = "user_id";
        // 初始化动态表字典
        Database.DynamicTableFields = new Dictionary<string, TableFieldConfig>();
    }

    internal class DatabaseSettings
    {
        internal FixedFieldNames FixedFieldNames { get; set; }
        // key为表名,存储动态表的字段配置
        internal Dictionary<string, TableFieldConfig> DynamicTableFields { get; set; }

        public DatabaseSettings()
        {
            FixedFieldNames = new FixedFieldNames();
        }

        internal class FixedFieldNames
        {
            internal UserTableFieldNames UserTable { get; set; }

            public FixedFieldNames()
            {
                UserTable = new UserTableFieldNames();
            }

            internal class UserTableFieldNames
            {
                internal string ID { get; set; }
                internal string Name { get; set; }
            }
        }
    }

    // 通用表字段配置类
    internal class TableFieldConfig
    {
        internal string ID { get; set; }
        internal string Name { get; set; }
        // 其他通用字段
    }
}

访问动态表字段:

// 获取已存在的动态表字段
if(LoadedData.Settings.Database.DynamicTableFields.TryGetValue("NewTable", out var fields))
{
    string newTableId = fields.ID;
}

// 添加新表配置
LoadedData.Settings.Database.DynamicTableFields["NewTable"] = new TableFieldConfig
{
    ID = "new_table_id",
    Name = "new_table_name"
};

序列化注意事项

因为类和属性都是internal,使用System.Text.Json时需添加[JsonInclude]或配置序列化器支持internal成员:

// System.Text.Json序列化示例
var options = new JsonSerializerOptions
{
    WriteIndented = true,
    IncludeFields = true,
    PropertyNameCaseInsensitive = true,
    // 允许访问internal成员
    Converters = { new JsonStringEnumConverter() }
};
// 保存
File.WriteAllText(settings.Filepath, JsonSerializer.Serialize(settings, options));
// 加载
var json = File.ReadAllText(settings.Filepath);
return JsonSerializer.Deserialize<MQSettings>(json, options) ?? new MQSettings();

使用Newtonsoft.Json时,可配置ContractResolver支持internal成员:

var jsonSettings = new JsonSerializerSettings
{
    ContractResolver = new DefaultContractResolver
    {
        DefaultMembersSearchFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
    },
    Formatting = Formatting.Indented
};

单例维护

你当前用LoadedData静态类持有实例的方式完全可行,确保启动时仅加载一次:

internal static class LoadedData
{
    internal static MQSettings Settings { get; } = Tools.Settings.Load();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:00:57