C#Protobuf反序列化

问题描述 投票:1回答:1

为什么Protobuf反序列化不适用于OffsetDictionary成员变量?如果我不将Dictionary用作后备字段,则效果很好。另外,如果将OffsetDictionary的类型从复杂类型更改为简单SortedDictionary,也可以正常工作。我在这里想念什么吗?

[ProtoContract]
Public class Test
{
    [ProtoMember(1)]
    public DateTime BaseDate {get; set;};

    [ProtoMember(2)]
    public SortedDictionary<short, SortedDictionary<short, uint>> OffsetDictionary
    {
        get
        {
            var output = new SortedDictionary<short, SortedDictionary<short, uint>>();
            if (this.Dictionary != null)
            {
                foreach (var item in this.Dictionary)
                {
                    var timeSpan = item.Key - this.BaseDate;
                    short offset = Convert.ToInt16(timeSpan.TotalDays);
                    output.Add(offset, item.Value);
                }
            }

            return output;
        }

        set
        {
            if (this.Dictionary == null)
            {
                this.Dictionary = new SortedDictionary<DateTime, SortedDictionary<short, uint>>();
            }

            foreach (var item in value)
            {
                this.Dictionary.Add(this.BaseDate.AddDays(item.Key), item.Value);
            }
        }
    }

    public SortedDictionary<DateTime, SortedDictionary<short, uint>> Dictionary { get; set; }
}
c# protocol-buffers protobuf-net protobuf-csharp-port
1个回答
0
投票
不需要。序列化器假定

合理地典型实现,在这种情况下,以下内容完全合理:

// when field 2 var val = obj.OffsetDictionary; bool setValue = false; if (val == null) { val = new SortedDictionary<short, SortedDictionary<short, uint>>(); setValue = true; } do { val.Add(/* parse this entry */); } while (/* still field 2 */) if (setValue) obj.OffsetDictionary = val; 尽管不是分配
开始时
(分配了setValue的地方也是合法的。

碰巧,您可以排序通过使用]来完成这项工作>

[ProtoMember(2, OverwriteList = true)]

但是... IMO出于错误的原因而工作,因为这也可以解释为相同地工作,但是只是添加.Clear(),不会改变输出。
坦白说,我不确定我是否真的喜欢这里的整体设计;就个人而言,我会保留数据[[以您要序列化的形式,并在Test上添加执行翻转的实用程序方法,即

[ProtoContract] public class Test { [ProtoMember(1)] public DateTime BaseDate { get; set; } [ProtoMember(2)] public SortedDictionary<short, SortedDictionary<short, uint>> OffsetDictionary { get; } = new SortedDictionary<short, SortedDictionary<short, uint>>(); private short ToInt16(DateTime value) => (short)(value - BaseDate).TotalDays; public void Add(DateTime key, SortedDictionary<short, uint> value) => OffsetDictionary.Add(ToInt16(key), value); public bool TryGetValue(DateTime key, out SortedDictionary<short, uint> value) => OffsetDictionary.TryGetValue(ToInt16(key), out value); }

但是,您也可以使用包装器层进行此操作-尽管这需要做很多工作:[ProtoContract] public class Test { [ProtoMember(1)] public DateTime BaseDate { get; set; } private DictionaryWrapper _offsetDictionary; [ProtoMember(2)] public IDictionary<short, SortedDictionary<short, uint>> OffsetDictionary => _offsetDictionary ?? (_offsetDictionary = new DictionaryWrapper(this)); public SortedDictionary<DateTime, SortedDictionary<short, uint>> Dictionary { get; } = new SortedDictionary<DateTime, SortedDictionary<short, uint>>(); class DictionaryWrapper : IDictionary<short, SortedDictionary<short, uint>> { public DictionaryWrapper(Test parent) { _parent = parent; } private readonly Test _parent; private DateTime ToDateTime(short value) => _parent.BaseDate.AddDays(value); private short ToInt16(DateTime value) => (short)(value - _parent.BaseDate).TotalDays; SortedDictionary<short, uint> IDictionary<short, SortedDictionary<short, uint>>.this[short key] { get => _parent.Dictionary[ToDateTime(key)]; set => _parent.Dictionary[ToDateTime(key)] = value; } int ICollection<KeyValuePair<short, SortedDictionary<short, uint>>>.Count => _parent.Dictionary.Count; bool ICollection<KeyValuePair<short, SortedDictionary<short, uint>>>.IsReadOnly => false; void IDictionary<short, SortedDictionary<short, uint>>.Add(short key, SortedDictionary<short, uint> value) => _parent.Dictionary.Add(ToDateTime(key), value); void ICollection<KeyValuePair<short, SortedDictionary<short, uint>>>.Add(KeyValuePair<short, SortedDictionary<short, uint>> item) => _parent.Dictionary.Add(ToDateTime(item.Key), item.Value); void ICollection<KeyValuePair<short, SortedDictionary<short, uint>>>.Clear() => _parent.Dictionary.Clear(); private ICollection<KeyValuePair<DateTime, SortedDictionary<short, uint>>> AsCollection => _parent.Dictionary; bool ICollection<KeyValuePair<short, SortedDictionary<short, uint>>>.Contains(KeyValuePair<short, SortedDictionary<short, uint>> item) => AsCollection.Contains(new KeyValuePair<DateTime, SortedDictionary<short, uint>>(ToDateTime(item.Key), item.Value)); bool IDictionary<short, SortedDictionary<short, uint>>.ContainsKey(short key) => _parent.Dictionary.ContainsKey(ToDateTime(key)); private IEnumerator<KeyValuePair<short, SortedDictionary<short, uint>>> GetEnumerator() { foreach (var item in _parent.Dictionary) yield return new KeyValuePair<short, SortedDictionary<short, uint>>(ToInt16(item.Key), item.Value); } IEnumerator<KeyValuePair<short, SortedDictionary<short, uint>>> IEnumerable<KeyValuePair<short, SortedDictionary<short, uint>>>.GetEnumerator() => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); bool IDictionary<short, SortedDictionary<short, uint>>.Remove(short key) => _parent.Dictionary.Remove(ToDateTime(key)); bool ICollection<KeyValuePair<short, SortedDictionary<short, uint>>>.Remove(KeyValuePair<short, SortedDictionary<short, uint>> item) => AsCollection.Remove(new KeyValuePair<DateTime, SortedDictionary<short, uint>>(ToDateTime(item.Key), item.Value)); bool IDictionary<short, SortedDictionary<short, uint>>.TryGetValue(short key, out SortedDictionary<short, uint> value) => _parent.Dictionary.TryGetValue(ToDateTime(key), out value); // these are kinda awkward to implement ICollection<short> IDictionary<short, SortedDictionary<short, uint>>.Keys => throw new NotSupportedException(); ICollection<SortedDictionary<short, uint>> IDictionary<short, SortedDictionary<short, uint>>.Values => throw new NotSupportedException(); void ICollection<KeyValuePair<short, SortedDictionary<short, uint>>>.CopyTo(KeyValuePair<short, SortedDictionary<short, uint>>[] array, int arrayIndex) => throw new NotSupportedException(); } }

© www.soinside.com 2019 - 2024. All rights reserved.