La sérialisation en C# avec une classe dérivée
Je suis en train de construire une notification cadre et pour qui je suis la sérialisation et la désérialisation d'une classe de base, à partir de laquelle toutes les classes je veux envoyer pourraient en tirer.
Le problème est que le code compile, mais quand je l'ai fait essayer à sérialiser cette classe de base, je reçois un message d'erreur indiquant que
Système.Moment de l'exécution.La sérialisation.SerializationException: Type 'Xxx.DataContracts.WQAllocationUpdate " dans l'Assembly 'Xxx.DataContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null " n'est pas marqué comme sérialisable.
Voici le code :
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; }
}
}
La DataContract
pour la Notification est:
///<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,
}
Le code utilisé pour sérialiser des données est:
#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
Lorsque j'essaie de créer un message:
WCallUpdate m_wCallUpdate = new WCallUpdate();
NotificationTypeKey m_notificationTypeKey = new NotificationTypeKey.Default;
CreateMessage(notificationTypeKey , wCallUpdate );
J'ai eu l'erreur suivante:
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
Si je mets de la Serializable drapeau avant la DataContract
on ne résout pas le problème.
merci pour la réponse rapide.
Désolé que j'ai oublié de mettre le code de la NotificationData (édité dans le poste principal)
J'ai essayé de mettre l'attribut Serializable de classe à la fois, sans succès 🙁
#region NotificationData
///<summary>
///Basic class used in the notification service
///</summary>
[Serializable]
[DataContract]
public class NotificationData
{
}
#endregion
et
[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; }
}
}
**Edit: ** Mea culpa après tout 🙂 Vous étiez tous les deux à droite.
J'ai oublié de propagation de la [Serializable]
attribuer à l'ensemble de la classe enfant.
Après la mise à jour et de la compilation, j'ai eu non plus l'exception.
merci à vous deux pour vos réponses 🙂
@Marc Gravier:
En fait j'ai pensé à ce que vous suggérez, et créé le DataContractSerializer, mais je ne suis pas sûr que cela va fonctionner? Comme mes classes à utiliser d'autres classes? le gros problème avec le DataContractSerializer est que vous avez besoin de spécifier le type de l'objet à sérialiser et que ma classe utilise une autre classe que les champs privés, qui pourrait causer un problème de droit?
#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
OriginalL'auteur srodriguez | 2009-04-16
Vous devez vous connecter pour publier un commentaire.
mettre [Serializable] dans le haut de la classe. Serializable n'est pas nécessairement héréditaire soit autant que je sache. ce qui signifie que même si la classe de base a [Serializable], vous avez encore besoin d'elle sur le descendant de la classe.
OriginalL'auteur Darren Kopp
Je suis très confus pourquoi vous utilisez
BinaryFormatter
avec une base de données de contrat. Il serait normal d'utiliserDataContractSerializer
ici... la logique est alors similaire à l'aide de[Serializable]
, sauf qu'il faut[DataContract
], et il sérialise les nominés ([DataMember]
) membres, plutôt que les champs quiBinaryFormatter
travaille avec.En fait, pour de nombreuses raisons (comme la fragilisation) je voudrais suggérer à
DataContractSerializer
, surtout que cela semble être votre intention. Ou si vous voulez un plus compact de forme binaire, protobuf-net peut être utile (plus est portable entre les plates-formes, trop).En aparté - vous n'avez pas besoin de la
[DataContract]
surenum
s - il ne fait pas de mal, mais ne fait pas beaucoup non plus.OriginalL'auteur Marc Gravell
Pour obtenir une classe sérialisable, il marque avec l'attribut serializable ou dérivé de MarshalByRefObject.
Vous dérivez de NotificationData, c'est sérialisable?
Également vérifier ce qui suit: lorsque serializable classes de données sont mis dans une assemblée de vérifier que votre projet ou votre référence de fichier dans Visual Studio pour être sûr que vous obtenez la bonne.
Aussi, si vous vous connectez à l'assemblée et le mettre dans le GAC, assurez-vous que l'assembly dans le GAC est la bonne! J'ai rencontré beaucoup de temps debugsessions parce que j'ai mis à jour l'assemblée à partir de la version 1.0.0.0 de 1.0.0.1 et j'ai oublié de remplacer l'ancien dans le GAC. Assemblées dans le GAC sont chargés avant les assemblées locales, gardez cela à l'esprit. Et... binaire mise en forme est très stricte relative à l'assemblée des versions.
OriginalL'auteur Patrick Peters
J'ai créé une classe XList pour ce faire:
Plus de détails peuvent être trouvés ici.
OriginalL'auteur David