2013-06-21 12 views
13

私たちはXmlSerializerを使用しています。私は特定のクラスに対してカスタムの直列化を提供したいと思います。しかし、私はいつも問題のクラスのソースコードを修正する能力を持っているとは限りません。そうでないと、IXmlSerializableを実装することができます。これを行う方法はありますか?ここでIXmlSerializableを実装せずにXmlSerializerのカスタムシリアル化を提供できますか?

+0

は、私はあなたが( 'XmlElement'、' XmlArray'、などなど)様々なXMLATTRIBUTESを持つクラスを飾ることができます知っているが、あなたは修正不可能なクラスのXML出力を制御する方法について、具体的求めていますか? –

+1

私は与えられたルートタグ名でIXmlSerializableを意味する "proxy"クラスを使い、ReadXml関数を使って実際の基底の値を構築します。そしてそれは公開プロパティに公開されます。 – asawyer

+0

型に使用されている属性を上書きできる[コンストラクタオーバーロード](http://msdn.microsoft.com/en-us/library/65k4wece.aspx)がありますが、 'IXmlSerializable.ReadXml'の動作/結果を変更します。編集:あなたのビジネスオブジェクトとサードパーティオブジェクト間のシリアル化の懸念を分離することはできますか? –

答えて

12

は、プロキシデシリアライズヘルパーの簡単な例です:

public sealed class Class //contrived example 
{ 
    public string Property {get;set;} 
} 

そして、我々がデシリアライズする必要があるのxml:

我々は直接クラスレベルでの直列化を制御することができないタイプを考えると

<Class> 
    <Property>Value</Property> 
</Class> 

ターゲットタイプの逆シリアル化プロセスを手作業で処理するプロキシタイプを作成することができます。

[XmlRoot("Class")] // <-- Very important 
public sealed class ClassSerializerProxy : IXmlSerializable 
{ 
    public Class ClassValue {get;set;} 

    public System.Xml.Schema.XmlSchema GetSchema(){return null;} 
    public void WriteXml(System.Xml.XmlWriter writer){} 

    public void ReadXml(System.Xml.XmlReader reader) 
    { 
     var x = XElement.ReadFrom(reader) as XElement; 
     this.ClassValue = new Class(); 
     //again this is a simple contrived example 
     this.ClassValue.Property = x.XPathSelectElement("Property").Value; 
    } 
} 

使い方は次のとおりです。

void Main() 
{ 
    // get the xml value somehow 
    var xdoc= XDocument.Parse(@"<Class><Property>Value</Property></Class>"); 

    // deserialize the xml into the proxy type 
    var proxy = Deserialize<ClassSerializerProxy>(xdoc); 

    // read the resulting value 
    var value = proxy.ClassValue; 
} 

public object Deserialize(XDocument xmlDocument, Type DeserializeToType) 
{ 
    XmlSerializer xmlSerializer = new XmlSerializer(DeserializeToType); 
    using (XmlReader reader = xmlDocument.CreateReader()) 
     return xmlSerializer.Deserialize(reader); 
} 

は現在、いくつかのジェネリック医薬品と拡張メソッドで投げ、そして我々は(例外処理を除く)最終版のためのビットを呼び出しサイトをクリーンアップすることができます

使用法:

void Main() 
{ 
    var xml = @"<Class><Property>Value</Property></Class>"; 

    var value = xml.DeserializeWithProxy<ClassSerializerProxy,Class>(); 

    value.Dump(); 
} 

あなたのインスタンスタイプ:

public sealed class Class 
{ 
    public string Property {get;set;} 
} 

インタフェースは、プロキシタイプは

public interface ISerializerProxy<TInstanceType> where TInstanceType : class 
{ 
    TInstanceType Value { get; } 
} 

を実装する必要があり、その例プロキシは、新しいインタフェース

[XmlRoot("Class")] 
public sealed class ClassSerializerProxy : IXmlSerializable, ISerializerProxy<Class> 
{ 
    public Class Value {get;set;} 

    public System.Xml.Schema.XmlSchema GetSchema(){return null;} 
    public void WriteXml(System.Xml.XmlWriter writer){} 

    public void ReadXml(System.Xml.XmlReader reader) 
    { 
     var x = XElement.ReadFrom(reader) as XElement; 
     this.Value = new Class(); 
     this.Value.Property = x.XPathSelectElement("Property").Value; 
    } 
} 

を実装するデシリアライゼーション方法についてstringに拡張メソッドであり、任意のプロキシで使用することができますタイプ。

public static class ExtensionMethods 
{ 
    public static TInstanceType DeserializeWithProxy<TProxyType,TInstanceType>(this string xml) 
     where TProxyType : ISerializerProxy<TInstanceType> 
     where TInstanceType : class 
    { 
     using (XmlReader reader = XDocument.Parse(xml).CreateReader()) 
     { 
      var xmlSerializer = new XmlSerializer(typeof(TProxyType)); 
      return (xmlSerializer.Deserialize(reader) as ISerializerProxy<TInstanceType>).Value; 
     } 
    } 
} 
+9

大きなオブジェクトツリーを持ち、ツリー全体のデフォルトのシリアル化を使用したいが、特定のリーフのカスタムシリアル化を使用したい場合、この方法を使用する方法はありますか?ソースにアクセスできる場合は、それらのリーフにIXmlSerializableを実装させ、カスタムシリアル化をそこに置くことができます。しかし、私が葉を変更できない場合は、ツリー全体のシリアル化コードを記述する必要がありますか?それとも、問題クラスの小さなサブセットをどうにかすることができますか? – Rob

+1

@asawyerこれはすばらしい答えです!私は、実際のクラスがXMLシリアライズ可能ではないので、WriteXml機能も実装することを選択しました。これは、コンストラクタでのみ設定できる読み取り専用アクセサの束で構成されています。 –

+0

@natephette私は助けることができたのでとてもうれしいです! – asawyer

関連する問題