C# 二进制格式化程序不';t反序列化IEnumerable上的对象
我有这些接口和类(您可以查看一下,以查看所有相关代码是否可编译)。为了描述这个问题,我只提供最少的代码(不可编译的代码): 我正在使用C# 二进制格式化程序不';t反序列化IEnumerable上的对象,c#,serialization,C#,Serialization,我有这些接口和类(您可以查看一下,以查看所有相关代码是否可编译)。为了描述这个问题,我只提供最少的代码(不可编译的代码): 我正在使用BinaryFormatter对它们进行序列化,它们(SelectedValueIViz.SelectValues属性上的对象)在文件中进行序列化 但是,当我试图反序列化它们时,它们不会被加载。我在SelectedValue(SerializationInfo,StreamingContext-context)constructor上添加了一个断点,但未到达该断点
BinaryFormatter
对它们进行序列化,它们(SelectedValue
IViz.SelectValues属性上的对象)在文件中进行序列化
但是,当我试图反序列化它们时,它们不会被加载。我在SelectedValue(SerializationInfo,StreamingContext-context)
constructor上添加了一个断点,但未到达该断点
我还尝试添加一个集代码>在IViz.SelectedValues
属性上实现,我还尝试将该属性设置为IList
而不是IEnumerable
。但是结果是一样的:我的SelectedValue
对象不会反序列化
有什么想法吗?我可以通过构造EntityValueGroupViz
的实例,添加SelectedValue(new BOEntity(),“hello”)
并序列化来重现您的问题。看一看
然而,为了达到重现问题的目的,我不得不:
- 将实体标记为
[Serializable]
- 将默认构造函数和流式构造函数添加到
GroupViz
和ValueGroupViz
- 在构造函数内的
GroupViz
中分配selectedValues
列表
- 将默认构造函数添加到
EntityValueGroupViz
一旦进行了这些初步修复,问题就会在EntityValueGroupViz
的流式构造函数中显现出来:
样品
只需序列化字段所在基类中选定值的列表BinaryFormatter
序列化流是完全类型化的,因此即使基类不知道集合中的子类型,也可以在其中存储selectedValues
字段:
[Serializable]
public abstract class GroupViz<T, TIn, TOut> : IViz<T>
{
// Added necessary default and streaming constructors
public GroupViz()
{
selectedValues = new List<SelectedValue>();
}
protected GroupViz(SerializationInfo info, StreamingContext context)
{
selectedValues = (IList<SelectedValue>)info.GetValue("SelectedValues", typeof(IList<SelectedValue>));
}
// Allocated the list
private IList<SelectedValue> selectedValues;
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("SelectedValues", selectedValues);
}
public IEnumerable<SelectedValue> SelectedValues
{
get { return selectedValues.Cast<SelectedValue>(); }
}
public void Value(SelectedValue @value)
{
this.AddValue(@value.Value, @value.Operator);
}
private void AddValue(object @value, object vizOperator)
{
SelectedValue<TOut> selectedValue = new SelectedValue<TOut>((TOut)value, vizOperator);
if (!this.selectedValues.Any(sv => sv.Equals(selectedValue)))
this.selectedValues.Add(selectedValue);
}
}
public abstract class ValueGroupViz<T, TIn> : GroupViz<T, TIn, TIn>
{
// Added necessary default and streaming constructors
public ValueGroupViz() : base() { }
protected ValueGroupViz(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
[Serializable]
public class EntityValueGroupViz<TEntity, TKey> : ValueGroupViz<TEntity, TKey>
{
// Added necessary default constructor.
public EntityValueGroupViz() : base() { }
protected EntityValueGroupViz(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
[可序列化]
公共抽象类GroupViz:IViz
{
//添加了必要的默认和流式构造函数
公共团体viz()
{
selectedValues=新列表();
}
受保护的GroupViz(SerializationInfo信息、StreamingContext上下文)
{
selectedValues=(IList)info.GetValue(“selectedValues”,typeof(IList));
}
//分配名单
私有IList选择值;
公共虚拟void GetObjectData(SerializationInfo信息、StreamingContext上下文)
{
info.AddValue(“SelectedValues”,SelectedValues);
}
公共IEnumerable SelectedValues
{
获取{返回selectedValues.Cast();}
}
公共无效值(SelectedValue@Value)
{
this.AddValue(@value.value,@value.Operator);
}
私有void AddValue(object@value,object-viz操作符)
{
SelectedValue SelectedValue=新的SelectedValue((TOut)值,vizOperator);
如果(!this.selectedValues.Any(sv=>sv.Equals(selectedValue)))
this.selectedValues.Add(selectedValue);
}
}
公共抽象类ValueGroupViz:GroupViz
{
//添加了必要的默认和流式构造函数
public ValueGroupViz():base(){}
受保护的ValueGroupViz(SerializationInfo,StreamingContext上下文):基(info,context){}
}
[可序列化]
公共类实体ValueGroupViz:ValueGroupViz
{
//添加了必要的默认构造函数。
public EntityValueGroupViz():base(){}
受保护的EntityValueGroupViz(SerializationInfo信息,StreamingContext上下文):基(信息,上下文){}
}
如您所见,此解决方案更简单,因此推荐使用
样品
谢谢你的评论。为了能够满足您的要求,我尝试添加每一个最小的反序列化相关代码。它已打开。好的,在EntityValueGroupViz
中如何反序列化SelectedValues
存在问题,但是中的测试代码不构造和存储此类型的实例,而是构造EntityQueryContext
的实例。基类中似乎有一个IList vizs
,但它不是公共的,也从未填充过。谢谢。据我所知,你是在暗示反序列化是有效的,然而,我还没有在任何地方找到我的viz
的内容(我认为这可能是代码写错了)。我想建议问一下,当序列化时到达SelectedValue.GetObjectData()
时,为什么在反序列化时到达任何SelectedValue(SerializationInfo,StreamingContext context)
构造函数。我希望我解释得这么好。亲爱的。我试着使用你写下的第二个选项。不幸的是,它一直在失败。我的意思是,正如您所猜测的:当case“SelectedValues”时:foreach(在(IEnumerable)entry.Value中的SelectedValue sv)this.Value(sv)代码>已到达sv为空
。我在GroupViz
、ValueGroupViz
和EntityValueGroupViz
上添加了默认的公共构造函数。我刚刚意识到,SelectedValue
没有默认的空构造函数…@Jordi-在第二个选项中,代码被完全删除。相反,在基类中有selectedValues=(IList)info.GetValue(“selectedValues”,typeof(IList))代码>
[Serializable]
public abstract class SelectedValue : ISerializable
{
public SelectedValue(SerializationInfo info, StreamingContext context)
{
Configuration.SerializationTemplatesEnum serializationTemplateEnum = (Configuration.SerializationTemplatesEnum)context.Context;
foreach (SerializationEntry entry in info)
{
switch (serializationTemplateEnum)
{
case Configuration.SerializationTemplatesEnum.QUERY:
switch (entry.Name)
{
case "Value":
Value = entry.Value;
break;
case "Operator":
Operator = (VizOperatorEnum)entry.Value;
break;
}
break;
case Configuration.SerializationTemplatesEnum.TEMPLATE:
break;
}
}
}
}
[Serializable]
public class SelectedValue<T> : SelectedValue, ISerializable
{
public SelectedValue(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
protected EntityValueGroupViz(SerializationInfo info, StreamingContext context)
{
foreach (SerializationEntry entry in info)
{
switch (entry.Name)
{
case "SelectedValues":
foreach (SelectedValue sv in (IEnumerable<SelectedValue>)entry.Value)
this.Value(sv);
break;
}
}
}
[Serializable]
public class EntityValueGroupViz<TEntity, TKey> : ValueGroupViz<TEntity, TKey>, IDeserializationCallback
{
IEnumerable<SelectedValue> cachedEntry;
// Added necessary default constructor.
public EntityValueGroupViz() : base() { }
protected EntityValueGroupViz(SerializationInfo info, StreamingContext context) : base(info, context)
{
foreach (SerializationEntry entry in info)
{
switch (entry.Name)
{
case "SelectedValues":
cachedEntry = (IEnumerable<SelectedValue>)entry.Value;
break;
}
}
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("SelectedValues", SelectedValues);
}
#region IDeserializationCallback Members
public void OnDeserialization(object sender)
{
if (cachedEntry != null)
{
foreach (SelectedValue sv in cachedEntry)
this.Value(sv);
cachedEntry = null;
}
}
#endregion
}
[Serializable]
public abstract class GroupViz<T, TIn, TOut> : IViz<T>
{
// Added necessary default and streaming constructors
public GroupViz()
{
selectedValues = new List<SelectedValue>();
}
protected GroupViz(SerializationInfo info, StreamingContext context)
{
selectedValues = (IList<SelectedValue>)info.GetValue("SelectedValues", typeof(IList<SelectedValue>));
}
// Allocated the list
private IList<SelectedValue> selectedValues;
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("SelectedValues", selectedValues);
}
public IEnumerable<SelectedValue> SelectedValues
{
get { return selectedValues.Cast<SelectedValue>(); }
}
public void Value(SelectedValue @value)
{
this.AddValue(@value.Value, @value.Operator);
}
private void AddValue(object @value, object vizOperator)
{
SelectedValue<TOut> selectedValue = new SelectedValue<TOut>((TOut)value, vizOperator);
if (!this.selectedValues.Any(sv => sv.Equals(selectedValue)))
this.selectedValues.Add(selectedValue);
}
}
public abstract class ValueGroupViz<T, TIn> : GroupViz<T, TIn, TIn>
{
// Added necessary default and streaming constructors
public ValueGroupViz() : base() { }
protected ValueGroupViz(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
[Serializable]
public class EntityValueGroupViz<TEntity, TKey> : ValueGroupViz<TEntity, TKey>
{
// Added necessary default constructor.
public EntityValueGroupViz() : base() { }
protected EntityValueGroupViz(SerializationInfo info, StreamingContext context) : base(info, context) { }
}