2011-07-12 23 views
2

こんにちは私はサービス契約を結んでおり、その実装では、受け取ったリクエストパラメータをテキストファイルに書き込もうとしています。ここでは、 'TypeA a'の複合オブジェクトがパラメータとして渡されます。入れ子にされた複合オブジェクトのWCF XMLシリアル化

 namespace WebService 
{ 
    // NOTE: If you change the interface name "IRequestStatusChanged" here, you must also update the reference to "IRequestStatusChanged" in App.config. 
    [ServiceContract] 
    public interface IRequestStatusChanged 
    { 
     [OperationContract] 
     Input StatusChanged(Input In); 

    } 

    [Serializable] [DataContract] 
    public class Input 
    { 
     [DataMember] 
     RequestStatus RS = new RequestStatus(); 

    } 

    [Serializable] [DataContract] 
    public class RequestStatus 
    { 
     [DataMember] 
     RequestToken RT = new RequestToken(); 

     [DataMember] 
     public String State 

    } 
    [Serializable] [DataContract] 
    public class RequestToken 
    { 
     [DataMember] 
     public string Id; 
    } 
} 

Implementation of contract 

namespace WebService 
{ 
    // NOTE: If you change the class name "RequestStatusChanged" here, you must also update the reference to "RequestStatusChanged" in App.config. 
    public class RequestStatusChanged : IRequestStatusChanged 
    { 
     public Input StatusChanged(Input In) 
     { 


      /* IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
      Stream outfile = new FileStream(@"C:\test.txt", FileMode.Open,FileAccess.Write); 
      formatter.Serialize(outfile, In); 
      outfile.Close(); */ 


      XmlSerializer serializer = new XmlSerializer(typeof(Input)); 
      TextWriter TW = new StreamWriter(@"c:\test.xml"); 
      serializer.Serialize(TW, In); 
      TW.Close(); 

      return In; 
     } 

    } 
} 

以前の私は、オブジェクトをシリアル化し、テキストファイルに書き込みIFORMATTERを試みたが、それが読める人間ではないので、私はXMLシリアル化を試みました。

書かれたXMLファイルをチェックすると、「TypeA」オブジェクトのタグだけがあり、「TypeB」および「TypeC」オブジェクトはファイルに書き込まれません。私はすべてのクラスをサービス契約で[Serializable]とマークしました。テキストまたはXML形式で受け取ったすべてのパラメータをファイルに書き込んで、読み込み可能なようにしたい(ログファイルのようなもの)。

+0

クライアントがTypeAオブジェクトを送信すると、TypeBのTypeCの値が設定されますか?シリアライザは、すべてがnullの場合、ファイルにこれらをコミットしていない可能性があります。 –

+0

はい、あります。それはnullではありません。 – user832219

答えて

2

タイプ 'TypeB'と 'TypeC'は、シリアライザがタイプAのインスタンスをシリアライズまたはデシリアライズしているときに、メンバー 'b' TypeBであるため、タイプ情報は書き込まれません。この情報も必要ですか? TypeAをシリアル化しているので、フィールドbのタイプがTypeBであることがわかっているので、その追加情報はログファイルには必要ありません。

WCFで使用されるすべてのシリアライザでは、タイプを常に強制的に書き込むことができるのはJSONシリアライザだけですが、結果はXMLではなくJSONとして取得されます。 。 (ロギングのために、あなたのシステムのロジックを変更することだろうと私は本当に、助言するものではありません)

public class StackOverflow_6666697 
{ 
    [DataContract] 
    public class TypeA { [DataMember] public TypeB b = new TypeB(); } 
    [DataContract] 
    public class TypeB { [DataMember] public TypeC c = new TypeC(); } 
    [DataContract] 
    public class TypeC { [DataMember] public string S1; } 
    public static void Test() 
    { 
     MemoryStream ms = new MemoryStream(); 
     XmlWriterSettings ws = new XmlWriterSettings 
     { 
      Indent = true, 
      IndentChars = " ", 
      OmitXmlDeclaration = true, 
      Encoding = Encoding.UTF8 
     }; 
     TypeA instance = new TypeA { b = new TypeB { c = new TypeC { S1 = "Hello world" } } }; 

     XmlWriter w = XmlWriter.Create(ms, ws); 
     new XmlSerializer(typeof(TypeA)).Serialize(w, instance); 
     w.Flush(); 
     Console.WriteLine("XmlSerializer:"); 
     Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 

     ms.SetLength(0); 
     w = XmlWriter.Create(ms, ws); 
     new DataContractSerializer(typeof(TypeA)).WriteObject(w, instance); 
     w.Flush(); 
     Console.WriteLine("DataContractSerializer:"); 
     Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 

     ms.SetLength(0); 
     w = XmlWriter.Create(ms, ws); 
     new NetDataContractSerializer().WriteObject(w, instance); 
     w.Flush(); 
     Console.WriteLine("NetDataContractSerializer:"); 
     Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 

     ms.SetLength(0); 
     w = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.UTF8); 
     new DataContractJsonSerializer(typeof(TypeA), null, 65536, false, null, true).WriteObject(w, instance); 
     w.Flush(); 
     Console.WriteLine("DataContractJsonSerializer:"); 
     Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 
    } 
} 

別のオプションは、objectとしてフィールドを宣言するだろう。このように、宣言された型は実際の型とは異なるため、型情報が書き出されます。以下を参照してください。

public class StackOverflow_6666697 
{ 
    [DataContract] 
    public class TypeA { [DataMember] public object b = new TypeB(); } 
    [DataContract] 
    public class TypeB { [DataMember] public object c = new TypeC(); } 
    [DataContract] 
    public class TypeC { [DataMember] public string S1; } 
    public static void Test() 
    { 
     MemoryStream ms = new MemoryStream(); 
     XmlWriterSettings ws = new XmlWriterSettings 
     { 
      Indent = true, 
      IndentChars = " ", 
      OmitXmlDeclaration = true, 
      Encoding = Encoding.UTF8 
     }; 
     TypeA instance = new TypeA { b = new TypeB { c = new TypeC { S1 = "Hello world" } } }; 

     XmlWriter w = XmlWriter.Create(ms, ws); 
     new XmlSerializer(typeof(TypeA), new Type[] { typeof(TypeB), typeof(TypeC) }).Serialize(w, instance); 
     w.Flush(); 
     Console.WriteLine("XmlSerializer:"); 
     Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 

     ms.SetLength(0); 
     w = XmlWriter.Create(ms, ws); 
     new DataContractSerializer(typeof(TypeA), new Type[] { typeof(TypeB), typeof(TypeC) }).WriteObject(w, instance); 
     w.Flush(); 
     Console.WriteLine("DataContractSerializer:"); 
     Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 

     ms.SetLength(0); 
     w = XmlWriter.Create(ms, ws); 
     new NetDataContractSerializer().WriteObject(w, instance); 
     w.Flush(); 
     Console.WriteLine("NetDataContractSerializer:"); 
     Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 

     ms.SetLength(0); 
     w = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.UTF8); 
     new DataContractJsonSerializer(typeof(TypeA), new Type[] { typeof(TypeB), typeof(TypeC) }, 65536, false, null, true).WriteObject(w, instance); 
     w.Flush(); 
     Console.WriteLine("DataContractJsonSerializer:"); 
     Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 
    } 
} 
+0

本当に有益な情報をありがとうございました。リクエストはXML形式で受信されるので、XML形式またはプレーンテキスト形式でファイルに書き込んで、読み取り可能にします。はい、TypeBとTypeCオブジェクトも記述する必要があります。複合オブジェクト全体をファイルに書き込む方法を見つけることができれば幸いです。 – user832219

+0

リクエストに必要なタイプ情報が含まれていますか?そのような場合は、MessageInspector(IDispatchMessageInspector)を使用してその時点で要求を記録することを検討できます。 – carlosfigueira

+0

*タイプ*情報が必要であるというOPの質問には何も表示されません。ネストされた値は書き込まれません。これは、 'XmlSerializer'が非公開のメンバーに接触しないためです。 – shambulator

0

XmlSerializerのみ公共メンバーをserialises。あなたが定義したタイプのメンバーのどれもがアクセス指定子を持っていないので、デフォルトではprivateになります。

ただし、ここでは別の2つのシリアライゼーションフレームワークを使用しています。DataContractSerializerは、特に指定しない限りWCFによって暗黙的に使用されています。XmlSerializerDataContractSerializerを使用するだけではなく、WCFの目的のために既に必要なすべての属性を持っているからです。

var serialiser = new DataContractSerializer(typeof(TypeA)); 
serialiser.WriteObject(xmlWriter, typeAObj); 
関連する問題