2009-07-17 35 views
1

私は、インタフェースIDeliveryを実装する2つのクラスSccmActionとTicketActionを持っています。これらのクラスは、メッセージを取得してDeliverメソッドで処理したい処理キューで送信されます。インタフェースへのXMLオブジェクトの逆シリアル化

私はそうしようとするとSystem.NotSupportedExceptionがスローされるので、私はインターフェイスに逆シリアル化できないようです。私が収集したことから、XMLSerializerには、シリアル化の具体的な型が必要です。これは、IDeliveryを実装し、そこからSccmActionとArsActionを継承する抽象クラスを作成しなければならないのですか?私は何かを逃したことがありますか?

編集さらに明確化

私は設計上の欠陥を持っているかもしれませんが、私の目的は、これらのオブジェクトを含むキューのオフにメッセージを引っ張っています。私の意図は、このキューからすべてのオブジェクトを取り除いて、オブジェクトを処理するアプリケーションがDeliverメソッドで動作することを保証するインタフェースを実装することでした。 Deliverの各オブジェクトの実装はさまざまです。

コードは

[Serializable] 
public class SccmAction : IDelivery 
{ 
    public string MachineName { get; set; } 
    public string CollectionName { get; set; } 
    public string Action { get; set; } 
    public DateTime EntryDateTime { get; set; } 

    public SccmAction() { } 

    public void Deliver() 
    { 
     throw new NotImplementedException(); 
    } 
} 

[Serializable] 
public class ArsAction : IDelivery 
{ 
    public string MachineName { get; set; } 
    public string CustomerName { get; set; } 

    public ArsAction() { } 

    public void Deliver() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public interface IDelivery 
{ 
    void Deliver(); 
} 
+0

XmlSerializerは型に対して '[Serializable]'を必要とせず、後者はバイナリの直列化用です。 –

+0

それを知りませんでした、チップをありがとう。 – ahsteele

答えて

4

簡単に言えば、あなたはどんな汚れなしのインターフェイスをシリアル化することはできません

using (SqlConnection connection = 
    new SqlConnection(ConnectionString)) 
{ 
    SqlCommand command = new SqlCommand(ReceiveString, connection); 
    connection.Open(); 

    SqlDataReader reader = command.ExecuteReader(); 

    while (reader.Read()) 
    { 
     byte[] sb = (byte[])reader["message_body"]; 
     SccmAction sa = DeserializeObject<SccmAction>(sb); 
     IDelivery iD = DeserializeObject<IDelivery>(sb); 
    } 

    reader.Close(); 
} 

public static T DeserializeObject<T>(byte[] ba) 
{ 
    XmlSerializer xs = new XmlSerializer(typeof(T)); 
    MemoryStream memoryStream = new MemoryStream(ba); 
    XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); 
    return (T)xs.Deserialize(memoryStream); 
} 

クラスとインターフェイスをデシリアライズします。しかし、どうしてあなたのインターフェイスをシリアル化したいのですが、それはどんな状態も保持しません。それはメソッドの宣言だけを持っています。

クラス内にSerializeメソッドを作成することができます。だから、彼らは自分たちを個別にシリアライズすることができます。

さらに、XmlSerializerはどのようにそれを提供せずに正確な型に逆シリアル化すると思いますか?それは単にあなたがにデシリアライズされているどのような種類を知らない場合は、しかし、この

IDelivery iD = DeserializeObject<SccmAction>(sb); 

にこのライン

IDelivery iD = DeserializeObject<IDelivery>(sb); 

を変更することができ

....にデシリアライズするかを選ぶことができません最初(ArsActionまたはSccmAction)、あなたはこのようなことをすることができます。

public static IDelivery DeserializeFromString(string xml) 
{ 
     //replace this stream with whatever you are useing 
     StringReader strReader = new StringReader(xml); 
     XmlReader reader = new XmlTextReader(fs); //important to use XmlReader 
     reader.MoveToContent(); //move to root 

     String className = reader.Name.Trim(); //read the class name 

     //use the namespace IDelivery is located in 
     className = "IDeliveryNamespace." + className; 

     //get the type 
     Type classType = Type.GetType(className); 

     XmlSerializer serializer = new XmlSerializer(Type.GetType(className));  

     // Declare an object variable of the type to be deserialized. 
     IDelivery i; 
     // Use the Deserialize method to restore the object's state. 
     i = (IDelivery)Convert.ChangeType(serializer.Deserialize(reader),classType); 
     return i; 
} 

もちろん、これはあなたのSerializableクラスの名前が変更されていないことを前提としています。意味ArsActionクラスは、あなたが投稿したものから私が知る限り、それとシリアル化します。

このコードは少し汚れていますが、出発点になるはずです。

+0

あなたの懸念に対応するように編集 – ahsteele

+0

IDelivery iD = DeserializeObject (sb);私はどのタイプがメッセージにシリアライズされているか知る必要がないようにしようとしています。 – ahsteele

+0

@ashteele:あなたはそれを言っている気がしました。私は私の答えを編集しました。 –

関連する問題