2012-06-27 2 views
7

私は自己ホストWCFサービスを構築しています。私は非常に柔軟なデータ転送のための特別なデータ構造を構築しています。これまでのところ、私は自分の構造体がDataContractSerializerを使ってシリアライズ可能かどうかをテストします。それは正常に動作し、私はそれについて満足しているが、何か迷惑な私にあります:私のXML出力で DataContractSerializerのXML名前空間をあらかじめ定義します

は数十属性のxmlnsを再定義しているが、例えば:これは、より良いルート要素で一度定義する必要があります

xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" 
xmlns:b="http://www.w3.org/2001/XMLSchema" 

バイトを単純に最適化することができます。ルート要素にカスタム名前空間情報を追加する方法はありますか?ここで

は、私が何を意味するか実証するための大きな一例です:

<DataObject xmlns="http://schemas.datacontract.org/2004/07/Test" 
      xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <Data xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"> 
    <a:KeyValueOfstringanyType> 
     <a:Key>ID</a:Key> 
     <a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">1</a:Value> 
    </a:KeyValueOfstringanyType> 
    <a:KeyValueOfstringanyType> 
     <a:Key>Value</a:Key> 
     <a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">42</a:Value> 
    </a:KeyValueOfstringanyType> 
    </Data> 
    <Data xmlns:a="...">...</Data> 
    <Data xmlns:a="...">...</Data> 
    <Data xmlns:a="...">...</Data> 
</DataObject> 

私が欲しいもの、このようなものです:

<DataObject xmlns="http://schemas.datacontract.org/2004/07/Test" 
      xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" 
      xmlns:b="http://www.w3.org/2001/XMLSchema"> 
    <Data> 
    <a:KeyValueOfstringanyType> 
     <a:Key>ID</a:Key> 
     <a:Value i:type="b:int">1</a:Value> 
    </a:KeyValueOfstringanyType> 
    <a:KeyValueOfstringanyType> 
     <a:Key>Value</a:Key> 
     <a:Value i:type="b:int">42</a:Value> 
    </a:KeyValueOfstringanyType> 
    </Data> 
    <Data>...</Data> 
    <Data>...</Data> 
    <Data>...</Data> 
</DataObject> 
+0

を(のhttp:/ /stackoverflow.com/questions/258960/how-to-serialize-an-object-to-xml-without-getting-xmlns)< - これはあなたが望むものを含んでいます –

+0

@ MarkusJarderotは本当にありません。それは一般的な名前空間を取り除く方法のようです。 WCF契約にはそれが必要です(これまでのところ私が知っています)!私はちょうどseverialの再定義があることを避けたいと思う。 – rekire

答えて

12
static void Main() 
{ 
    var o = new Foo { 
     Prop = new Dictionary<string,string> { {"foo","bar"} } 
    }; 

    var ms = new MemoryStream(); 

    var slz = new DataContractSerializer(typeof(Foo)); 
    slz.WriteObject(ms, o, 
     new Dictionary<string,string> 
     { 
      { "arr", "http://schemas.microsoft.com/2003/10/Serialization/Arrays" }, 
     }); 

    string data = Encoding.UTF8.GetString(ms.ToArray()); 
    Console.WriteLine(data); 
} 

public static class Extensions 
{ 
    public static void WriteObject(
     this DataContractSerializer serializer, 
     Stream stream, object data, 
     Dictionary<string,string> namespaces) 
    { 
     using (var writer = XmlWriter.Create(stream)) 
     { 
      serializer.WriteStartObject(writer, data); 
      foreach (var pair in namespaces) 
      { 
       writer.WriteAttributeString("xmlns", pair.Key, null, pair.Value); 
      } 
      serializer.WriteObjectContent(writer, data); 
      serializer.WriteEndObject(writer); 
     } 
    } 
} 

[DataContract] 
class Foo 
{ 
    [DataMember] 
    public Dictionary<string,string> Prop; 
} 

出力:

<?xml version="1.0" encoding="utf-8"?> 
<Foo xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays" 
    xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://schemas.datacontract.org/2004/07/"> 
    <Prop> 
     <arr:KeyValueOfstringstring> 
      <arr:Key>foo</arr:Key> 
      <arr:Value>bar</arr:Value> 
     </arr:KeyValueOfstringstring> 
    </Prop> 
</Foo> 
+0

それは完璧に見えます。私のためにその宣言を加える属性がないということは残念です。 – rekire

+0

@rekire http://stackoverflow.com/a/6574024/22364 –

+0

これは適切な解決策のようです。ありがとうございました! 'DataContractSerializer'はすべてうまく動作します。しかし、 'DataContractJsonSerializer'は' DataContractResolver'についてのSerializationExceptionをスローするか、 'KnownTypeAttribute'を使うべきです。なぜ、 'DataContractJsonSerializer'は' DataContractSerializer'を必要としませんか? – rekire

2

Iここに記載されているソリューションをうまく使用:http://blogs.msdn.com/b/youssefm/archive/2009/07/24/optimizing-away-repeat-xml-namespace-declarations-with-datacontractserializer.aspx

基本的にルート要素に名前空間を追加する動作を作成します。記事から

はちょうどそれがトップレベルに追加の名前空間を登録しているという事実を除いて、すべてのメソッドのためにDataContractSerializerを使用していますXmlObjectSerializerを継承するシリアライザを作成します。次に、作成したばかりの XmlObjectSerializerを返す CreateSerializerメソッドを使用して DataContractSerializerOperationBehaviorから派生した動作を作成し、プラグインします。あなたはSilverlightでそれをしたい場合には

、あなたもここで説明するソリューションを使用することができます:[どのようにのxmlnsを取得せずにオブジェクトをXMLにシリアライズする=「...」?] http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/24/wcf-extensibility-custom-serialization-in-silverlight.aspx

関連する問題