自己实现 RDM Formatter(MessagePack/.NET 6.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 内容了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352

推荐阅读更多精彩内容