ProtoBuf -迁移到新版本

本文关键字:新版本 迁移 ProtoBuf | 更新日期: 2023-09-27 18:17:35

我最近迁移到新版本的protobuf-net,在

之后我开始收到这个错误消息

重复的数据(列表,集合等)具有内置行为,不能用作子类

调用堆栈跟踪

protobuf-net.dll!ProtoBuf.Meta.MetaType.AddSubType(int fieldNumber = 1, System.Type derivedType = {Name = "InfoColumn`1" FullName = "Om.Common.InfoSet.InfoColumn`1[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}) Line 83    C#
protobuf-net.dll!ProtoBuf.Meta.MetaType.ApplyDefaultBehaviour() Line 431 + 0x32 bytes   C#

在这方面的任何帮助都是感激的。我计划回滚我的代码到以前版本的protobuf-net

下面是类信息。

[DataContract]
[ProtoInclude(1, typeof(InfoColumn<Double>))]
[ProtoInclude(2, typeof(InfoColumn<String>))]
[ProtoInclude(3, typeof(InfoColumn<DateTime>))]
[ProtoInclude(4, typeof(InfoColumn<Boolean>))]
public abstract class IInfoColumnBase 
{
    [DataMember(Order = 101)]
    public abstract bool IsSingleValue { get; set; }
    [DataMember(Order = 102)]
    public abstract string Name { get; set; }
    [DataMember(Order = 103)]
    public abstract InfoColumnDataType DataType { get; set; }
    public abstract long Insert();
    public abstract void Insert(long index);
    public abstract void SetValue(long index, object val);
    public abstract void CopyValues(long start, long end, IInfoColumnBase destCol, long index);
    public abstract long GetIndex(object val);
    public abstract void Remove(long index);
    public abstract object GetValue(long index);
    public abstract object GetInternalArrayValue(long index);
    public abstract void Clear();
    public abstract long Count { get; }
    public abstract long ArrayCount { get; }
}
public interface IInfoColumn<T>  : IEnumerable<T>
{
    T this[double index] { get; set; }
    InfoTable Table { get; set; }
    double Add(T item);
}

[DataContract(Name = "InfoColumn{0}")]
[KnownType(typeof(InfoColumn<double>))]
[KnownType(typeof(InfoColumn<String>))]
[KnownType(typeof(InfoColumn<bool>))]
[KnownType(typeof(InfoColumn<DateTime>))]
public class InfoColumn<T> : IInfoColumnBase, IInfoColumn<T> 
{
    long counter = 0;
    [DataMember(Order = 1)]
    public IList<T> Values { get; set; }
    //[DataMember(Order = 2)]
    bool isSingleVal = false;
    //[DataMember(Order=3)]
    public override string Name { get; set; }
    //[DataMember(Order=4)]
    public override InfoColumnDataType DataType { get; set; }
    public InfoTable Table { get; set; }

    public override long Count
    {
        get
        {
            return this.Table.Count;
        }
    }
    public override long ArrayCount
    {
        get { return this.Values.Count; } 
    }
    public InfoColumn()
    {
    }
    public InfoColumn(string name,InfoTable table)
    {
        this.Values = new List<T>();
        this.Name = name;
        this.Table = table;
    }
    public override void Clear()
    {
        this.Values = new List<T>();
    }
    public override void Remove(long index)
    {
        int newindex = (int)index;
        this.Values.RemoveAt(newindex);
    }

    public override void CopyValues(long start, long end, IInfoColumnBase destCol, long startIndex)
    {
        InfoColumn<T> typeCol = destCol as InfoColumn<T>;
        for (long ctr = start; ctr <= end; ctr++)
        {
            typeCol.SetValue(startIndex, this.Values[(int)ctr]);
            startIndex++;
        }
    }
    public override void Insert(long rows)
    {
        if (this.IsSingleValue == true) return;
        for (int ctr = 0; ctr < rows; ctr++)
        {
            this.Values.Add(default(T));
        }
    }
    public  T this[double a]
    {
        get
        {
            if (a >= this.Count) throw new IndexOutOfRangeException();
            long index = (long)a;
            if (this.Table.IsFreezed == false)
                index = this.Table.CheckData(a);

            if (this.isSingleVal == true)
                return this.Values[0];
            else 
                return this.Values[(int)index];
        }
        set
        {
            if (a >= this.Count) throw new IndexOutOfRangeException();
            long index = (long)a; 
            if (this.Table.IsFreezed == false)
                index = this.Table.CheckData(a);
            if (this.isSingleVal == true)
                this.Values[0] = value;
            else
                this.Values[(int)index] = value;
        }
    }
    public override long GetIndex(object val)
    {
        T item = (T)val;
        return this.Values.IndexOf(item);
    }
    public override void SetValue(long index, object val)
    {
        if (val is InfoSetLink)
            this.Values[(int)index] = (T)val;
        else
            this.Values[(int)index] = (T)Convert.ChangeType(val, typeof(T));
    }
    public override object GetValue(long index)
    {
        return this[index];
    }
    public override object GetInternalArrayValue(long index)
    {
        return this.Values[(int)index];
    }

    //[DataMember(Order=5)]
    public override bool IsSingleValue 
    {
        get { return isSingleVal; }
        set
        {
            if (isSingleVal == true)
            {
                this.Values = new List<T>(1);
            }
        }
    }
    public override long Insert()
    {
        if (this.IsSingleValue == true) return -1;
        this.Values.Add(default(T));
        return this.Values.Count - 1;
    }
    public double Add(T item)
    {
        this.Values.Add(item);
        return this.Values.Count - 1;
    }
    #region IEnumerable<T> Members
    public IEnumerator<T> GetEnumerator()
    {
        return new InfoColumnEnumerator<T>(this);
    }
    #endregion
    #region IEnumerable Members
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return new InfoColumnEnumerator<T>(this);
    }
    #endregion

}

ProtoBuf -迁移到新版本

InfoColumn<T>有一个公共Add(T),并通过IInfoColumn<T>实现IEnumerable<T>

在v2中对类列表类型有更广泛的支持,这可能是它试图将上面的解释为列表。确实,它看起来很像!我将尝试查看是否可以检测和避免这种一般情况,但这是一个边缘情况(因为它确实非常类似于列表)。

有一个现有的IgnoreListBehaviour开关,但是在验证上面所示的模型时,似乎对于这个特定的场景,"你不能这样做"在禁用列表处理的代码之前触发;我已经在源代码中更改了这一点,这将包含在下一个版本中。基本上,您可以通过添加:

来解决这个问题:
[ProtoContract(IgnoreListHandling = true)]

到受影响的类型(InfoColumn<T>),下一个构建。这将很快,只要我完成验证等