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

如何以跨兼容方式扩展.NET枚举类型且不改动原有依赖类库?

解决方案

核心实现(基于.NET Standard 2.0 原生API)

核心思路是实现一个全局线程安全的枚举扩展注册中心,所有模块遵循该规范读写扩展格式信息即可,完全不需要修改原有类库代码。

第一步:定义格式元数据类

用于存储每个格式对应的名称、自定义属性等信息:

public sealed class ImageFormatMetadata
{
    public string Name { get; }
    public IReadOnlyDictionary<string, object> CustomProperties { get; }

    public ImageFormatMetadata(string name, Dictionary<string, object> customProperties = null)
    {
        Name = name ?? throw new ArgumentNullException(nameof(name));
        CustomProperties = customProperties ?? new Dictionary<string, object>();
    }
}

第二步:实现全局注册中心

采用静态类实现,进程内所有模块共享注册信息,内置重复注册校验:

public static class ImageFormatRegistry
{
    private static readonly ConcurrentDictionary<ImageFormat, ImageFormatMetadata> _valueToMetadata = new();
    private static readonly ConcurrentDictionary<string, ImageFormat> _nameToValue = new(StringComparer.OrdinalIgnoreCase);

    static ImageFormatRegistry()
    {
        // 初始化原生枚举值的映射
        foreach (ImageFormat nativeValue in Enum.GetValues(typeof(ImageFormat)))
        {
            RegisterInternal(nativeValue, nativeValue.ToString(), skipDuplicateCheck: true);
        }
    }

    public static void Register(ImageFormat value, string name, Dictionary<string, object> customProperties = null)
    {
        RegisterInternal(value, name, skipDuplicateCheck: false, customProperties);
    }

    private static void RegisterInternal(ImageFormat value, string name, bool skipDuplicateCheck, Dictionary<string, object> customProperties = null)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new ArgumentException("格式名称不能为空", nameof(name));

        if (!skipDuplicateCheck)
        {
            if (_valueToMetadata.ContainsKey(value))
                throw new InvalidOperationException($"ImageFormat值 {(int)value} 已被注册");
            if (_nameToValue.ContainsKey(name))
                throw new InvalidOperationException($"ImageFormat名称 {name} 已被注册");
        }

        var metadata = new ImageFormatMetadata(name, customProperties);
        _valueToMetadata.TryAdd(value, metadata);
        _nameToValue.TryAdd(name, value);
    }

    public static bool TryGetMetadata(ImageFormat value, out ImageFormatMetadata metadata)
    {
        return _valueToMetadata.TryGetValue(value, out metadata);
    }

    public static bool TryParse(string formatName, out ImageFormat value)
    {
        return _nameToValue.TryGetValue(formatName, out value);
    }
}

使用方式

扩展格式注册

各模块在初始化阶段注册自己的扩展格式即可,不需要和其他使用方模块交互:

// 模块启动时执行一次
public static void RegisterCustomFormats()
{
    ImageFormatRegistry.Register(
        value: (ImageFormat)100003,
        name: "Webp",
        customProperties: new Dictionary<string, object>
        {
            ["MimeType"] = "image/webp",
            ["FileExtensions"] = new[] { ".webp" },
            ["SupportTransparency"] = true
        });
}

格式信息读取

任意模块都可以直接读取全局注册的格式信息,不需要引用注册方的程序集:

// 从Image实例读取格式信息
if (ImageFormatRegistry.TryGetMetadata(image.Format, out var metadata))
{
    Console.WriteLine($"当前格式:{metadata.Name}");
    Console.WriteLine($"对应的MIME类型:{metadata.CustomProperties["MimeType"]}");
}

// 从名称解析格式
if (ImageFormatRegistry.TryParse("Webp", out var webpFormat))
{
    // 处理Webp格式逻辑
}

特性匹配验证

  • 给定ImageFormat值可直接获取名称和自定义属性,不需要反射/ToString:底层是字典查找,性能远高于反射
  • 给定字符串可解析得到对应ImageFormat值:内置TryParse方法直接实现
  • 能力可被任意模块使用,单个模块修改全局可见:静态注册中心同AppDomain内全局共享
  • 通信模块无需互相引用:所有模块仅依赖注册中心定义即可,注册方和使用方不需要直接引用
  • 注册安全,重复注册可检测:注册方法内置值、名称的重复校验,异常信息明确
  • 无随意性设计:核心就是全局映射存储,逻辑直白无隐藏规则
  • 兼容.NET Standard 2.0:所有用到的API均在.NET Standard 2.0支持范围内

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:51:02