7

自己ホスト型の WCF サービスを構築しています。非常に柔軟なデータ転送のための特別なデータ構造を構築しています。これまでのところ、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>
4

2 に答える 2

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>
于 2012-06-27T08:12:52.097 に答える
2

ここで説明されているソリューションを正常に使用しました: http://blogs.msdn.com/b/youssefm/archive/2009/07/24/optimizing-away-repeat-xml-namespace-declarations-with-datacontractserializer.aspx

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

記事から:

トップレベルで追加の名前空間を登録するという事実を除いて、すべてのメソッドに対して DataContractSerializer を使用する XmlObjectSerializer から継承するシリアライザーを作成するだけです。次に、作成したを返すメソッドを使用DataContractSerializerOperationBehaviorして派生する動作を作成し、動作をプラグインします。CreateSerializerXmlObjectSerializer

Silverlight で実行する場合は、ここで説明されているソリューションを使用することもできます: http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/24/wcf-extensibility-custom-serialization-in -silverlight.aspx

于 2012-09-28T16:58:39.490 に答える