使用派生类在C#中进行序列化

使用派生类在C#中进行序列化,c#,serialization,derived-class,C#,Serialization,Derived Class,我正在构建一个通知框架,为此我正在序列化和反序列化一个基本类,我要发送的所有类都将从中派生 问题是代码是可以编译的,但是当我实际尝试序列化这个基本类时,我得到一个错误 System.Runtime.Serialization.SerializationException:程序集“Xxx.DataContracts,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”中的类型“Xxx.DataContracts.WQAllocationUpdat

我正在构建一个通知框架,为此我正在序列化和反序列化一个基本类,我要发送的所有类都将从中派生

问题是代码是可以编译的,但是当我实际尝试序列化这个基本类时,我得到一个错误

System.Runtime.Serialization.SerializationException:程序集“Xxx.DataContracts,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”中的类型“Xxx.DataContracts.WQAllocationUpdate”未标记为可序列化

代码如下:

public class WCallUpdate : NotificationData
{
    private string m_from = "";
    [DataMember]
    public string From
    {
        get { return m_from; }
        set { m_from = value; }
    }
    private WCall m_wCall = new WCall();
    [DataMember]
    public WCall Call
    {
        get { return m_wCall; }
        set { m_wCall = value; }
    }
}
通知的
DataContract
为:

/// <summary>
/// Basic class used in the notification service
/// </summary>
[DataContract]
public class NotificationData
{
}

/// <summary>
/// Enum containing all the events used in the application
/// </summary>
[DataContract]
public enum NotificationTypeKey
{
    [EnumMember]
    Default = 0,
    [EnumMember]
    IWorkQueueServiceAttributionAddedEvent = 1,
    [EnumMember]
    IWorkQueueServiceAttributionUpdatedEvent = 2,
    [EnumMember]
    IWorkQueueServiceAttributionRemovedEvent = 3,
}
我得到了以下错误:

System.Runtime.Serialization.SerializationException: Type 'Xxx.DataContracts.WCall' in Assembly 'Xxx.DataContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
   at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
   at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
   at Xxx.Notification.NotificationMessageFactory.CreateMessage(NotificationTypeKey notificationTypeKey, NotificationData notificationData) in Xxx.Notification\NotificationCenter.cs:line 36
如果我将Serializable标志放在
DataContract
之前,则无法解决问题


谢谢你的快速回答。 很抱歉,我忘了把通知数据的代码放进去(在主帖子中编辑)

我尝试将Serializable属性放入这两个类,但均未成功:(

**编辑:*毕竟我有罪:)你们都是对的。 我忘记将
[Serializable]
属性扩展到所有子类。 经过更新和编译,我不再得到异常。 谢谢你们两位的正确回答:)


@碎石: 实际上,我考虑了您的建议,并创建了以下DataContractSerializer,但我不确定这是否可行?我的课程使用其他课程吗?DataContractSerializer的一个大问题是,您需要指定要序列化的对象的类型,因为我的类使用其他类作为私有字段,这可能会导致问题,对吗

#region DataContractSerializer
        /// <summary>
        /// Creates a Data Contract Serializer for the provided type. The type must be marked with
        /// the data contract attribute to be serialized successfully.
        /// </summary>
        /// <typeparam name="T">The type to be serialized</typeparam>
        /// <returns>A data contract serializer</returns>
        public static DataContractSerializer CreateDataContractSerializer<T>() where T : class
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(T));
            return serializer;
        }
        #endregion
#区域数据序列化程序
/// 
///为提供的类型创建数据协定序列化程序。类型必须标记为
///要成功序列化的数据协定属性。
/// 
///要序列化的类型
///数据协定序列化程序
公共静态DataContractSerializer CreateDataContractSerializer(),其中T:class
{
DataContractSerializer serializer=新的DataContractSerializer(typeof(T));
返回序列化程序;
}
#端区

要获取可序列化的类,请使用serializable属性对其进行标记,或从MarshallByRefObject派生该类

您从NotificationData派生,那么它可以序列化吗

还要检查:当可序列化数据类放入程序集中时,请在VisualStudio中检查项目或文件引用,以确保获得正确的引用


此外,如果您在程序集上签名并将其放入GAC,请确保GAC中的程序集是正确的!我遇到了许多耗时的调试会话,因为我将程序集从版本1.0.0.0更新到了版本1.0.0.1,并且忘记在GAC中替换旧的程序集。请记住,GAC中的程序集是在本地程序集之前加载的。而且。。。二进制格式对于程序集版本非常严格。

将[Serializable]放在类的顶部。Serializable也不一定是AFAIK继承的。这意味着,即使基类具有[Serializable],您仍然需要在子类上使用它。

我很不明白为什么要将
BinaryFormatter
与数据协定一起使用。在这里使用
DataContractSerializer
是正常的。。。然后,该逻辑类似于使用
[Serializable]
,只是您需要
[DataContract
],它序列化指定的(
[DataMember]
)成员,而不是
BinaryFormatter
使用的字段

实际上,出于许多原因()我建议切换到
DataContractSerializer
,尤其是因为这似乎是您的意图。或者,如果您想要更紧凑的二进制格式,可能会很有用(此外,还可以在平台之间移植)


顺便说一句-您不需要
enum
s上的
[DataContract]
-它没有坏处,但也没有太多作用。

我创建了一个类XList来完成此任务:

AA D1=new AA(); //Derived type
BB D2=new BB(); //Derived type 
CC D3=new CC(); //Derived type 
X D4=new X(); //Base Class 

XList<X> AllData=new XList<X>(); 
AllData.Add(D1); 
AllData.Add(D2); 
AllData.Add(D3); 
AllData.Add(D4); 
// ----------------------------------- 
AllData.Save(@"C:\Temp\Demo.xml"); 
// ----------------------------------- 
// Retrieve data from XML file 
// ----------------------------------- 
XList<X> AllData=new XList<X>(); 
AllData.Open(@"C:\Temp\Demo.xml"); 
// -----------------------------------
AA D1=新的AA()//派生类型
BB D2=新的BB()//派生类型
CC D3=新的CC()//派生类型
X D4=新的X()//基类
XList AllData=new XList();
所有数据。添加(D1);
添加所有数据(D2);
添加所有数据(D3);
添加所有数据(D4);
// ----------------------------------- 
保存(@“C:\Temp\Demo.xml”);
// ----------------------------------- 
//从XML文件检索数据
// ----------------------------------- 
XList AllData=new XList();
打开(@“C:\Temp\Demo.xml”);
// -----------------------------------

可以找到更多详细信息。

我很困惑为什么要将BinaryFormatter与数据契约一起使用(此评论现在扩展为答案)。Marc是正确的。使用DataContractSerializer。它还允许您以二进制形式序列化。下面是一些代码:using(var fs=newfilestream(FILE_NAME,FileMode.Create,FileAccess.Write)){using(var reader=XmlDictionaryWriter.CreateBinaryWriter(fs)){var dcs=newDataContractSerializer(typeof(NotificationData));dcs.WriteObject(reader,true); } }
#region NotificationData
/// <summary>
/// Basic class used in the notification service
/// </summary>
[Serializable]
[DataContract]
public class NotificationData
{
}
#endregion
[Serializable]
public class WCallUpdate : NotificationData
{
    private string m_from = "";
    [DataMember]
    public string From
    {
        get { return m_from; }
        set { m_from = value; }
    }
    private WCall m_wCall = new WCall();
    [DataMember]
    public WCall Call
    {
        get { return m_wCall; }
        set { m_wCall = value; }
    }
}
#region DataContractSerializer
        /// <summary>
        /// Creates a Data Contract Serializer for the provided type. The type must be marked with
        /// the data contract attribute to be serialized successfully.
        /// </summary>
        /// <typeparam name="T">The type to be serialized</typeparam>
        /// <returns>A data contract serializer</returns>
        public static DataContractSerializer CreateDataContractSerializer<T>() where T : class
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(T));
            return serializer;
        }
        #endregion
AA D1=new AA(); //Derived type
BB D2=new BB(); //Derived type 
CC D3=new CC(); //Derived type 
X D4=new X(); //Base Class 

XList<X> AllData=new XList<X>(); 
AllData.Add(D1); 
AllData.Add(D2); 
AllData.Add(D3); 
AllData.Add(D4); 
// ----------------------------------- 
AllData.Save(@"C:\Temp\Demo.xml"); 
// ----------------------------------- 
// Retrieve data from XML file 
// ----------------------------------- 
XList<X> AllData=new XList<X>(); 
AllData.Open(@"C:\Temp\Demo.xml"); 
// -----------------------------------