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) { }
    }