我最近迁移到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
}
答案 0 :(得分:0)
InfoColumn<T>
有公开Add(T)
并实施IEnumerable<T>
(通过IInfoColumn<T>
)。
v2中对类似列表的类型有更广泛的支持,可能是它试图将上面的内容解释为列表。确实,它确实看起来很像!我将尝试看看是否可以检测并避免这种一般情况,但它是一个边缘情况(因为它确实非常列表式)。
有一个现有的IgnoreListBehaviour
开关,但是在为上面显示的模型验证时,似乎对于此特定情况“你不能这样做”在禁用列表处理的代码;我在源代码中对此进行了更改,这将包含在下一个版本中。基本上,您可以通过添加以下内容来解决此问题:
[ProtoContract(IgnoreListHandling = true)]
到受影响的类型(InfoColumn<T>
),下一步构建。我很快就会完成验证等。