美文网首页
自己实现 RDM Formatter(MessagePack/.

自己实现 RDM Formatter(MessagePack/.

作者: 缺水的海豚 | 来源:发表于2021-12-18 16:31 被阅读0次

    用 RDM(Redis Desktop Manager)有一段时间了,本想找个现成的用 .NET 反序列化 MessagePack 的 Formatter,但是资源很少,好不容易找的一个,还不能用,所以,就自己实现了 RDM MessagePack Formatter。

    注意:本文用 C# 只实现了 MessagePack 的反序列化和在 RDM 中显示,若要通过 RDM 以 MessagePack 序列化后添加到 Redis 中,目前还未实现。

    本文涉及的产品和组件

    1. RDM(Redis Desktop Manager)2021.8 GitHub
    2. RDM Formatter 说明文档 | GitHub
    3. System.Text.Json (.NET 6.0 / Visual Studio 2022 / Windows)
    4. MessagePack 2.3.85 GitHub | NuGet

    1 安装 RDM

    就按常规安装好 RDM 后,在安装目录中,找到 formatters 目录,在里面新建一个目录(名称可自定义,方便记忆就好,最好用字母),在步骤 4 要用。

    2 建立项目

    用 VS 建立一个项目(类库或控制台应用都可以),项目(RDMMsgPackFormatter)结构如下所示:

    <Project Sdk="Microsoft.NET.Sdk">
    
        <PropertyGroup>
            <OutputType>Exe</OutputType>
            <TargetFramework>net6.0</TargetFramework>
            <ImplicitUsings>enable</ImplicitUsings>
        </PropertyGroup>
    
        <ItemGroup>
            <PackageReference Include="MessagePack" Version="2.3.85" />
        </ItemGroup>
    
        <ItemGroup>
            <None Update="usage.json">
                <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            </None>
        </ItemGroup>
    
    </Project>
    

    RDM Formatter 需要一个配置文件,叫 usage.json,建议用 UTF-8 格式,全部内容如下所示:

    [ "dotnet", "RDMMsgPackFormatter.dll" ]
    

    注意:数组第二项,填入 dll 文件,请勿填入 exe 文件!!!

    3 撸码

    在项目中,添加 Program.cs 文件,完整内容如下:

    using MessagePack;
    
    using System.Text.Json;
    using System.Text.Json.Serialization;
    
    namespace RDMMsgPackFormatter;
    
    public class Program
    {
        // System.Text.Json 序列化配置
        private static readonly JsonSerializerOptions _jsonOpts;
    
        static Program()
        {
            _jsonOpts = new JsonSerializerOptions
            {
                IncludeFields = true,
                AllowTrailingCommas = true,
                PropertyNameCaseInsensitive = true,
                ReadCommentHandling = JsonCommentHandling.Skip,
                DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase
            };
        }
    
        static void Main(string[] args)   // 主入口
        {
            if (args is { Length: > 0 })
            {
                switch (args[0])
                {
                    case "info":   // Formatter 基本信息标识
                        Info();
                        break;
                    case "decode":   // Formatter 反序列化标识
                        Decode();
                        break;
                    case "encode":   // Formatter 序列化标识
                        // 暂未实现
                        break;
                }
            }
        }
    
        private static void Info()
        {
            // 用 Console.Write() 对 RDM 输出要显示的内容
            Console.Write(JsonSerializer.Serialize(new FormatterInfo(), _jsonOpts));
        }
    
        private static void Decode()
        {
            try
            {
                char[] charsInput;
                byte[] bytes;
                string input, json;
    
                // 通过 Console.ReadLine() 读取 RDM 输入的内容
                while ((input = Console.ReadLine()) is not null)
                {
                    // RDM 输入的内容,是:binary-data-encoded-with-base64
                    // 以下用 MessagePackSerializer.ConvertToJson(byte[]) 将输入的内容转换为 json 字符串
                    charsInput = input.ToCharArray();
                    bytes = Convert.FromBase64CharArray(charsInput, 0, charsInput.Length);
                    json = MessagePackSerializer.ConvertToJson(bytes);
    
                    // 用 Console.Write() 输出的内容,格式如下:
                    // {
                    //     "output": "要在 RDM 中显示的可读的内容"
                    //     "read-only": true(结果不可编辑)false(结果可编辑)
                    //     "format": "plain_text" 或 "json"
                    // }
                    Console.Write(JsonSerializer.Serialize(new FormatterDecode(json, NeedJsonFormat(json)), _jsonOpts));
                }
            }
            catch (Exception e)
            {
                // 反序列化失败的异常信息
                Console.Write(JsonSerializer.Serialize(new FormatterError(e.Message), _jsonOpts));
            }
        }
    
        // 该方法,主要是用于判断字符串内容是否是 json 对象或 json 数组,方便最终格式化输出并显示
        private static bool NeedJsonFormat(string content)
        {
            var doc = JsonDocument.Parse(content);
            return doc.RootElement.ValueKind is JsonValueKind.Object or JsonValueKind.Array;
        }
    }
    
    /// <summary>
    /// Formatter 信息的实体类
    /// </summary>
    public class FormatterInfo
    {
        public string Version { get; private set; } = ".NET 6.0";
    
        public string Description { get; private set; } = "Dotnet MessagePack formatter";
    
        /// <summary>
        /// true:默认值,不显示在添加数据的对话框的下拉菜单中
        /// false:将显示在添加数据的对话框的下拉菜单中
        /// </summary>
        [JsonPropertyName("read-only")]
        public bool ReadOnly { get; private set; } = false;
    }
    
    /// <summary>
    /// Formatter 序列化/反序列化失败的实体类
    /// </summary>
    public class FormatterError
    {
        public FormatterError(string error)
        {
            Error = error;
        }
    
        public string Error { get; private set; }
    }
    
    /// <summary>
    /// Formatter 返序列化输出的实体类
    /// </summary>
    public class FormatterDecode
    {
        public FormatterDecode(string output, bool isJson = false)
        {
            Output = output;
            Format = isJson ? "json" : "plain_text";
        }
    
        /// <summary>
        /// 输出到 RDM 的内容
        /// </summary>
        public string Output { get; private set; }
    
        /// <summary>
        /// 输出到 RDM 的内容是否可以编辑
        /// </summary>
        [JsonPropertyName("read-only")]
        public bool ReadOnly { get; private set; } = true;
    
        /// <summary>
        /// 输出到 RDM 的内容格式化方式
        /// (仅支持 plain_text 和 json 两种方式)
        /// </summary>
        public string Format { get; private set; }
    }
    

    4 安装到 RDM 中

    撸完码后编译,将编译得到的所有文件(exe 除外)拷贝到步骤 1 中新建的目录内,内容如下图所示:

    步骤 1 新建目录内的全部内容

    5 使用 RDM

    完成步骤 4 后,重新打开 RDM,即可正常显示 Redis 中的 MessagePack 内容了。

    相关文章

      网友评论

          本文标题:自己实现 RDM Formatter(MessagePack/.

          本文链接:https://www.haomeiwen.com/subject/jhjgfrtx.html