ProtoBuf - 迁移到新版本

时间:2011-12-11 19:49:48

标签: c# protobuf-net

我最近迁移到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


}

1 个答案:

答案 0 :(得分:0)

InfoColumn<T>有公开Add(T)并实施IEnumerable<T>(通过IInfoColumn<T>)。

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

有一个现有的IgnoreListBehaviour开关,但是在为上面显示的模型验证时,似乎对于此特定情况“你不能这样做”在禁用列表处理的代码;我在源代码中对此进行了更改,这将包含在下一个版本中。基本上,您可以通过添加以下内容来解决此问题:

[ProtoContract(IgnoreListHandling = true)]

到受影响的类型(InfoColumn<T>),下一步构建。我很快就会完成验证等。