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

优化Discord/Revolt/IRC桥接服务嵌套配置遍历方案咨询

优化跨平台聊天桥接服务的配置解析逻辑

我正在构建一个跨Discord、Revolt及两个独立IRC网络的专用桥接服务,目标是实现匿名性且方便其他用户配置。在处理桥接通道配置时,Discord和Revolt的配置很简单,但IRC网络的配置比较特殊——不同IRC网络的配置没有固定键名,而是用提前定义的网络名称作为键。

配置格式与实体类

设计的TOML配置如下:

[[bridge]]
    [bridge.chat]
    discord = "<discord-channel-id>"
    revolt = "<revolt-channel-id>"
    libera = "#<channel-name>"
    oftc = "#<channel-name>"

所有配置键均为非必填项,libera、oftc这类键可替换为任意提前定义的IRC网络名称。

对应的C#实体类:

public class bridges
{
    string bridgeName = "";

    Dictionary<string, string> ircChannels = new Dictionary<string, string>();
    string revoltChannel = "";
    ulong discordChannel = 0;
    bool hasIrcConnection = false;
    // 省略getter/setter
}

当前问题

目前采用嵌套遍历解析配置,在switch-case处理完Discord/Revolt后,还要嵌套foreach遍历IRC网络列表匹配键,效率较低:

case "bridge":
    foreach(TomlTable table in tArr)
    {
        foreach(string tableKey in table.Keys)
        {
            bridges bridge = new bridges();
            bridge.BridgeName = tableKey;
            foreach(var item in (TomlTable)table[bridge.BridgeName])
            {
                switch (item.Key)
                {
                    case "discord":
                        bridge.DiscordChannel = (ulong)item.Value;
                        break;
                    case "revolt":
                        bridge.RevoltChannel = (string)item.Value;
                        break;                                                
                }
                foreach (string server in ircCommunityNames)
                // ircCommunityNames为提前初始化的IRC网络名称列表,示例:["libera", "oftc"]
                {
                    if(server == item.Key)
                    {
                        bridge.IrcChannels.Add(server, (string)item.Value);
                    }  
                }

            }
            if(bridge.IrcChannels.Count > 0)
            {
                bridge.HasIrcConnection = true;
            }
            bridgeConfigs.Add(bridge);

        }
    }
    break;

希望避免这种嵌套多重遍历的低效逻辑,求更优实现方案。


优化方案

1. 用HashSet替代List,消除内层遍历

将ircCommunityNames从List<string>转为HashSet<string>,这样判断键是否属于IRC网络的时间复杂度从O(n)降至O(1),直接去掉内层foreach循环。

2. 合并逻辑,单次遍历完成所有处理

遍历每个配置项时,先处理Discord/Revolt的固定键,再用HashSet快速判断当前键是否为IRC网络名称,一次遍历完成所有赋值:

优化后的代码:

// 提前初始化HashSet,替换原List<string> ircCommunityNames
HashSet<string> ircServerSet = new HashSet<string>(ircCommunityNames);

case "bridge":
    foreach(TomlTable table in tArr)
    {
        foreach(string tableKey in table.Keys)
        {
            bridges bridge = new bridges();
            bridge.BridgeName = tableKey;
            var chatTable = (TomlTable)table[tableKey];
            
            foreach(var item in chatTable)
            {
                var key = item.Key;
                var value = item.Value;
                
                // 处理固定平台配置,处理完直接跳过后续判断
                switch (key)
                {
                    case "discord":
                        bridge.DiscordChannel = (ulong)value;
                        continue;
                    case "revolt":
                        bridge.RevoltChannel = (string)value;
                        continue;
                }
                
                // 快速判断并添加IRC通道配置
                if(ircServerSet.Contains(key))
                {
                    bridge.IrcChannels.Add(key, (string)value);
                }
            }
            
            bridge.HasIrcConnection = bridge.IrcChannels.Count > 0;
            bridgeConfigs.Add(bridge);
        }
    }
    break;

3. 进阶优化:利用TOML序列化库自动映射

如果使用TOML序列化库(如Tomlyn、Nett),可以通过自定义映射规则省去手动遍历代码:

  • 实体类中保留Discord/Revolt的固定属性,用Dictionary<string, string>接收未匹配的键值对
  • 后续仅需过滤字典中属于ircCommunityNames的项即可

示例(以Tomlyn为例):

public class BridgeConfig
{
    [TomlProperty("discord")]
    public ulong DiscordChannel { get; set; }
    
    [TomlProperty("revolt")]
    public string RevoltChannel { get; set; }
    
    public Dictionary<string, string> IrcChannels { get; set; } = new();
    
    // 捕获所有未匹配的键值对
    [TomlIgnore]
    private Dictionary<string, object>? _extraProperties;
    
    [TomlConstructor]
    public BridgeConfig(TomlTable table)
    {
        // 自动填充固定属性
        Tomlyn.Model.TomlModelSerializer.Default.Deserialize(table, this);
        
        // 过滤IRC网络配置
        if(_extraProperties != null)
        {
            foreach(var kvp in _extraProperties)
            {
                if(ircServerSet.Contains(kvp.Key) && kvp.Value is string channel)
                {
                    IrcChannels.Add(kvp.Key, channel);
                }
            }
        }
    }
}

这种方式代码更简洁,维护成本更低,适合长期迭代。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 08:43:13