protobuf网:如何序列化复杂收藏? [英] Protobuf-net: How to serialize complex collection?

查看:191
本文介绍了protobuf网:如何序列化复杂收藏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用protobuf网序列化此类型的对象:

I'm trying to serialize this type of object using 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
}

我用列表<对象> 。因为我存储其他类我在我的代码有不同的类实例

I'm using List<object> because I'm storing there different class instances of other classes I have in my code.

但我发现了此错误消息:

But I'm getting this error message:

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

这显然是因为字典的,但我无法找到一个解决方案如何解决这个问题。

This is clearly because of the dictionary, but I couldn't find a solution how to resolve this issue.

推荐答案

您基本的问题是 DynamicType = TRUE 仅适用于特定属性,序列化该特定属性的值类型信息只。它不递归适用于任何由该对象包含的属性。然而,你的对象值容器的几个层次深处的嵌套:

Your basic problem is that DynamicType = true applies to that specific property only, and serializes type information for the value of that specific property only. It doesn't apply recursively to any of the properties contained by that object. However, your object value is nested deep within several levels of container:

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

您需要做的是序列化每个对象本词典列出的元组内。您可以通过引入一个替代值类型做到这一点:

What you need to do is to serialize type information for each object inside this dictionary of tuples of lists. You can do this by introducing a surrogate value type:

[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 连载的替代字典如下:

And then modifying your RedisDataObject to serialize a surrogate dictionary as follows:

[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 的限制提到的这里

Note also the restrictions on DynamicType mentioned here:

DynamicType - 存储额外键入同类型的信息(默认情况下它包括 AssemblyQualifiedName ,虽然这可以由用户控制)。这使得序列化弱模型,即其中对象是用于物业会员,但目前这仅限于合同类型(不是原语) ,并且不为类型与继承工作(这些限制可能在以后的时间被删除)。像 AsReference ,使用了一种非常不同的布局格式

DynamicType - stores additional Type information with the type (by default it includes the AssemblyQualifiedName, although this can be controlled by the user). This makes it possible to serialize weak models, i.e. where object is used for property members, however currently this is limited to contract types (not primitives), and does not work for types with inheritance (these limitations may be removed at a later time). Like with AsReference, this uses a very different layout format

虽然文档上述存在于href=\"https://code.google.com/archive/p/protobuf-net/\" rel=\"nofollow\">前项目现场并没有被移动到<一的目前的网站,对非合同类型的限制肯定仍然存在为2.0.0.668版本。 (我测试了加入 INT 值到列表<对象> 失败;我没有检查是否限制上继承仍然存在。)

While the documentation above exists at the former project site and has not been moved to the current site, the restriction on non-contract types definitely still exists as of version 2.0.0.668. (I tested that adding an int value to the List<object> fails; I have not checked whether the restriction on inheritance still exists.)

这篇关于protobuf网:如何序列化复杂收藏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆