4

私は通知フレームワークを構築しています。そのために、送信したいすべてのクラスが派生する基本クラスをシリアライズおよびデシリアライズしています。

問題はコードがコンパイルされることですが、実際にこの基本クラスをシリアライズしようとすると、エラーが発生します

System.Runtime.Serialization.SerializationException: アセンブリ 'Xxx.DataContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' の Type '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,
}

データのシリアル化に使用されるコードは次のとおりです。

    #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]属性をすべての子クラスに広げるのを忘れていました。更新してコンパイルした後、例外が発生しなくなりました。あなたの正しい答えをありがとう:)


@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
4

4 に答える 4

20

[Serializable]をクラスの一番上に置きます。シリアル化可能は、必ずしもAFAIKを継承する必要はありません。つまり、基本クラスに[Serializable]がある場合でも、子孫クラスでそれが必要です。

于 2009-04-16T05:53:40.137 に答える
6

なぜあなたがBinaryFormatterデータ契約を使用しているのか、私は非常に混乱しています。ここで使用するのは普通のことDataContractSerializerです... ロジックは を使用するのと似ていますが、][Serializable]が必要であり、動作するフィールドではなく[DataContract、指定された ( ) メンバーをシリアル化します。[DataMember]BinaryFormatter

実際には、多くの理由 (脆弱性などDataContractSerializer) から、特にそれがあなたの意図のように思われるため、 に切り替えることをお勧めします。または、よりコンパクトなバイナリ形式が必要な場合は、protobuf-netが役立つ場合があります (さらに、プラットフォーム間でも移植可能です)。

余談ですが、[DataContract]onは必要ありenumません。害はありませんが、あまり効果もありません。

于 2009-04-16T07:10:56.677 に答える
0

これを実現するためにクラス 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"); 
// -----------------------------------

詳細については、こちらをご覧ください

于 2011-03-08T06:51:54.247 に答える