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

标签 c# serialization derived-class

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

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

System.Runtime.Serialization.SerializationException: Type 'Xxx.DataContracts.WQAllocationUpdate' in Assembly 'Xxx.DataContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as 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; }
    }
}

通知的 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,
}

用于序列化数据的代码是:

    #region Create Message
    /// <summary>
    /// Creates a memoryStream from a notificationData
    /// note: we insert also the notificationTypeKey at the beginning of the
    /// stream in order to treat the memoryStream correctly on the client side
    /// </summary>
    /// <param name="notificationTypeKey"></param>
    /// <param name="notificationData"></param>
    /// <returns></returns>
    public MemoryStream CreateMessage(NotificationTypeKey notificationTypeKey, NotificationData notificationData)
    {
        MemoryStream stream = new MemoryStream();
        BinaryFormatter formatter = new BinaryFormatter();
        try
        {
            formatter.Serialize(stream, notificationTypeKey);
            formatter.Serialize(stream, notificationData);
        }
        catch (Exception ex)
        {
            Logger.Exception(ex);
        }
        return stream;
    }
    #endregion

当我尝试创建消息时:

WCallUpdate  m_wCallUpdate = new WCallUpdate();
NotificationTypeKey  m_notificationTypeKey = new NotificationTypeKey.Default;
CreateMessage(notificationTypeKey , wCallUpdate );

我收到以下错误:

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 之前,则不能解决问题。


感谢您的快速回答。 对不起,我忘了放 NotificationData 的代码(在主帖中编辑)

我尝试将 Serializable 属性添加到两个类,但没有成功:(

#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; }
    }
}

**编辑:**毕竟是我认错了:)你们都是对的。 我忘了将 [Serializable] 属性传播到所有子类。 更新和编译后,我不再是异常。 谢谢你们的正确答案:)


@马克砾石: 实际上,我考虑了您的建议,并创建了以下 DataContractSerializer,但我不确定这是否有效?当我的类(class)使用其他类(class)时? DataContractSerializer 的一个大问题是您需要指定要序列化的对象的类型,并且由于我的类使用其他类作为私有(private)字段,这可能会导致问题,对吗?

#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

最佳答案

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

关于c# - 使用派生类在 C# 中进行序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/754850/

相关文章:

c# - 创建一个包含对象数组的类

c# - 从 derived 而不是 base 调用的虚拟方法

c++ - 从派生类访问基类的 protected 数据成员

c# - 自定义(派生)List<T>

c# - int 是枚举的支持类型

c# - 当我在 Visual Studio 中生成以二维数组作为参数的构造函数时,这些星号是什么?

c# - 如何解决应用了 Authorize 属性的 MVC Controller 的鸡生蛋依赖关系解析?

php - 将 4 字节大整数写为无符号二进制

python - 如何将 Python 内存字典作为 Python 源代码保存到文件中?

C++ 将对象写入文件然后再读入?