Protobuf-net:如何序列化复杂的集合?

2023-12-29

我正在尝试使用 protobuf-net 序列化此类对象:

[ProtoContract]
public class RedisDataObject
{
    [ProtoMember(1)]
    public string DataHash;
    [ProtoMember(2, DynamicType = true)]
    public Dictionary<ContextActions, List<Tuple<string, List<object>>>> Value;
}

[Serializable]
public enum ContextActions
{
    Insert,
    Update,
    Delete
}

我在用着List<object>因为我在那里存储了代码中其他类的不同类实例。

但我收到此错误消息:

Unable to resolve a suitable Add method for System.Collections.Generic.Dictionary...

这显然是因为字典的原因,但我找不到解决此问题的解决方案。


你的基本问题是DynamicType = true仅适用于该特定属性,并且仅序列化该特定属性的值的类型信息。它不会递归地应用于该对象包含的任何属性。然而,你的object值嵌套在容器的多个级别中:

public Dictionary<ContextActions, List<Tuple<string, List<object>>>> Value;

您需要做的是序列化每个的类型信息object在这个列表元组字典中。您可以通过引入代理值类型来做到这一点:

[ProtoContract]
public struct DynamicTypeSurrogate<T>
{
    [ProtoMember(1, DynamicType = true)]
    public T Value { get; set; }
}

public static class DynamicTypeSurrogateExtensions
{
    public static List<DynamicTypeSurrogate<T>> ToSurrogateList<T>(this IList<T> list)
    {
        if (list == null)
            return null;
        return list.Select(i => new DynamicTypeSurrogate<T> { Value = i }).ToList();
    }

    public static List<T> FromSurrogateList<T>(this IList<DynamicTypeSurrogate<T>> list)
    {
        if (list == null)
            return null;
        return list.Select(i => i.Value).ToList();
    }
}

然后修改你的RedisDataObject按如下方式序列化代理字典:

[ProtoContract]
public class RedisDataObject
{
    [ProtoMember(1)]
    public string DataHash;

    [ProtoIgnore]
    public Dictionary<ContextActions, List<Tuple<string, List<object>>>> Value;

    [ProtoMember(2)]
    private Dictionary<ContextActions, List<Tuple<string, List<DynamicTypeSurrogate<object>>>>> SurrogateValue
    {
        get
        {
            if (Value == null)
                return null;
            var dictionary = Value.ToDictionary(
                p => p.Key,
                p => (p.Value == null ? null : p.Value.Select(i => Tuple.Create(i.Item1, i.Item2.ToSurrogateList())).ToList()));
            return dictionary;
        }
        set
        {
            if (value == null)
                Value = null;
            else
            {
                Value = value.ToDictionary(
                    p => p.Key,
                    p => (p.Value == null ? null : p.Value.Select(i => Tuple.Create(i.Item1, i.Item2.FromSurrogateList())).ToList()));
            }
        }
    }
}

另请注意以下限制DynamicType提及here https://code.google.com/archive/p/protobuf-net/wikis/Attributes.wiki:

DynamicType- 存储额外的Type类型信息(默认情况下它包括AssemblyQualifiedName,尽管这可以由用户控制)。这使得序列化弱模型成为可能,即object用于财产成员,但目前仅限于contract类型(不是基元),并且不适用于具有继承的类型(这些限制可能稍后会被删除)。喜欢与AsReference,这使用了非常不同的布局格式

虽然上述文档存在于原项目工地 https://code.google.com/archive/p/protobuf-net/并且还没有被移动到当前站点 https://github.com/mgravell/protobuf-net/wiki,从 2.0.0.668 版本开始,对非合约类型的限制肯定仍然存在。 (我测试了添加一个int的价值List<object>失败;我没有检查继承的限制是否仍然存在。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Protobuf-net:如何序列化复杂的集合? 的相关文章

  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐