sro*_*uez 4 c# serialization derived-class
我正在构建一个通知框架,为此我将序列化和反序列化一个基本类,我想要发送的所有类都将从中派生.
问题是代码编译,但当我实际尝试序列化这个基本类时,我得到一个错误说
System.Runtime.Serialization.SerializationException:在Assembly'Xxx.DataContract中键入'Xxx.DataContracts.WQAllocationUpdate',Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'未标记为可序列化.
这是代码:
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; }
}
}
Run Code Online (Sandbox Code Playgroud)
在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,
}
Run Code Online (Sandbox Code Playgroud)
用于序列化数据的代码是:
#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
Run Code Online (Sandbox Code Playgroud)
当我尝试创建消息时:
WCallUpdate m_wCallUpdate = new WCallUpdate();
NotificationTypeKey m_notificationTypeKey = new NotificationTypeKey.Default;
CreateMessage(notificationTypeKey , wCallUpdate );
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
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
Run Code Online (Sandbox Code Playgroud)
如果我把Serializable标志放在DataContract一个之前没有解决问题.
谢谢你的快速回答.对不起,我忘了把NotificationData的代码(在主帖中编辑)
我尝试将Serializable属性放到这两个类中但没有成功:(
#region NotificationData
/// <summary>
/// Basic class used in the notification service
/// </summary>
[Serializable]
[DataContract]
public class NotificationData
{
}
#endregion
Run Code Online (Sandbox Code Playgroud)
和
[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; }
}
}
Run Code Online (Sandbox Code Playgroud)
**编辑:**Mea culpa afterall :)你们都是对的.我忘了将[Serializable]属性传播给所有子类.更新和编译后,我不再是例外.谢谢你们两个正确答案:)
@Marc Gravel:其实我考虑过你的建议,并创建了以下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
Run Code Online (Sandbox Code Playgroud)
我很困惑你为什么要使用BinaryFormatter数据合同.DataContractSerializer在这里使用是正常的...逻辑然后类似于使用[Serializable],除了你需要[DataContract],它序列化了指定的([DataMember])成员,而不是使用的字段BinaryFormatter.
实际上,出于多种原因(例如脆性),我建议改用DataContractSerializer,特别是因为这似乎是你的意图.或者如果你想要一个更紧凑的二进制形式,protobuf-net可能是有用的(加上也可以在平台之间移植).
顺便说一句-你不需要[DataContract]在enum秒-它没有任何伤害,但不会做了很多无论是.