ProtoBuf - переход на новую версию - PullRequest
2 голосов
/ 11 декабря 2011

Я недавно перешел на новую версию 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 голосов
/ 12 декабря 2011

InfoColumn<T> имеет общедоступный Add(T) и реализует IEnumerable<T> (через IInfoColumn<T>).

В v2 существует более широкая поддержка спискообразных типов, и может случиться так, что он пытаетсяинтерпретировать вышеизложенное как список.Который действительно, это выглядит очень похоже!Я попытаюсь посмотреть, можно ли обнаружить и избежать этого общего сценария, но это крайний случай (поскольку он действительно очень похож на список).

Существует существующий переключатель IgnoreListBehaviourоднако при проверке этого для модели, показанной выше, кажется, что для этого конкретного сценария «вы не можете сделать это» срабатывает до того, как код, отключающий обработку списка;Я изменил это в источнике, и это будет включено в следующий выпуск.По сути, вы можете решить эту проблему, добавив:

[ProtoContract(IgnoreListHandling = true)]

к затронутому типу (InfoColumn<T>) со сборкой next .Что будет в ближайшее время, как только я завершу проверку и т. Д.

...