2009-06-24 10 views
7

は、私は(自明シンプル)は、次の基本クラスがあるとします。継承されたメンバーに属性を適用できますか?

public class Simple 
{ 
    public string Value { get; set; } 
} 

私は今、次の操作を実行したい:

public class PathValue : Simple 
{ 
    [XmlAttribute("path")] 
    public string Value { get; set; } 
} 

public class ObjectValue : Simple 
{ 
    [XmlAttribute("object")] 
    public string Value { get; set; } 
} 

しかし、実際にプロパティを再定義せずに。私は基本クラスのメンバーに属性を適用したいです。これは可能ですか?

実際の問題は、私のシリアル化の仕組みがXMLから(素晴らしいbtwで動作します)、属性の名前だけが異なる(それらは一貫性がなく、フォーマットを制御する)。今は、そのような要素ごとに異なるクラスを作成する必要がありますが、それらは100%同じです(属性とは別に)。

私はそれは可能ではないと思いますが、あなたは決して知りません。

UPDATE:

私は、しかし、無駄に、マークのアプローチを試してみました:

public class Document 
{ 
    public PathValue Path; 
    public ObjectValue Object; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var doc = new Document() 
     { 
      Path = new PathValue() { Value = "some path" }, 
      Object = new ObjectValue() { Value = "some object" } 
     }; 

     XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 

     overrides.Add(typeof(PathValue), "Value", new XmlAttributes() { XmlAttribute = new XmlAttributeAttribute("path") }); 
     overrides.Add(typeof(ObjectValue), "Value", new XmlAttributes() { XmlAttribute = new XmlAttributeAttribute("object") }); 

     XmlSerializer serializer = new XmlSerializer(typeof(Document), overrides); 

     serializer.Serialize(Console.Out, doc); 

     Console.WriteLine(); 
     Console.ReadLine(); 
    } 
} 

...トリックを行いません。

+0

シンプルから継承するつもりだと思います。 – Noldorin

+0

これは、単一のxmlファイルに、の両方の要素を含めることができることを意味しますか? – Groo

+0

彼らは明らかに派生クラスにシリアライズする必要があります。要素自体の名前は使用されている場所に依存しますが、それは一般的な考えです。 また、私のアプリケーションでは、より一般的には、XMLを書き出すのに使われています。 –

答えて

3

私はこの質問に自分自身で答えるつもりです。私はこの答えを受け入れることができます。私はその答えが嫌いですが、それが唯一の有効な答えだと思います。

答えは:いいえ、できません。

2

実行時に適用する属性を渡すことができるオーバーロードXmlSerializerコンストラクタを使用できますか?あなたはそれについて心配する必要はありません...

注意:シリアライザインスタンスをキャッシュして再利用したいと思います。それ以外の場合(複合コンストラクタを使用)、毎回動的型生成を行います。

例:

using System; 
using System.Xml.Serialization; 
public class Simple { 
    public string Value { get; set; } 

    static void Main() { 
     XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 
     overrides.Add(typeof(Simple), "Value", new XmlAttributes { 
      XmlAttribute = new XmlAttributeAttribute("path") 
     }); 
     XmlSerializer pathSerializer = new XmlSerializer(
      typeof(Simple), overrides); 
     // cache and re-use pathSerializer!!! 

     Simple obj = new Simple(); 
     obj.Value = "abc"; 
     pathSerializer.Serialize(Console.Out, obj); 
    } 
} 

出力:

<Simple xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" path="abc" /> 
+0

これはうまくいくかもしれませんが、派生クラスに対してオーバーライドを指定することはできません。ですから、属性の名前が異なるインスタンスごとにシリアライザを用意する必要がありますが、これらの異なる要素はすべて同じドキュメントに表示されることがあります。 –

0

あなたは、おそらくこのことを認識しているが、アイデア(コード構造が完全にそのような場合に変更するだろうが)のように:

1つの方法は、カスタムクラスのシリアル化を使用して、名前と値のペアのコレクションとして基本クラスをシリアル化することです(XDocumentなどの便利なものもあります)。型の安全性を強制するものではありませんが、手作業を大量に行うことはありません。

私はまた、より広い範囲の可能性(例えば、不変クラスをシリアライズする)を可能にするため、カスタムシリアル化を優先します。また、XmlSerializerは時には本当に面倒です(たとえば、オプション属性を作成するために "MyFieldSpecified"プロパティを追加することは嫌です)。

+0

私のアプリケーションでは、私はXMLの生成のための特別なモデルを持っています。つまり、「ドメインモデル」と「xmlモデル」があり、2つは実際に分離されています。 XmlSerializerのカスタマイズ性のために、このアプローチを使用してXmlWriterを使用してXMLファイルを生成することにしました。 ドメインモデルは、BinaryFormatterを使用してシリアル化されています。 –

0

おそらく、基本クラスのプロパティを共通のマッピングでマークすることができます。ただし、継承されたクラスのプロパティが異なる必要がある場合にのみ、そのプロパティをオーバーライドします。少なくともあなたはいくつかのオーバーライドを保存します。

1

これはどう:

public class Simple 
{ 
    [XmlIgnore] 
    public string Value { get; set; } 
} 

public class PathValue : Simple 
{ 
    [XmlAttribute("path")] 
    public string Path { 
      get { return base.Value != null ? base.Value : null; } 
      set { base.Value = value != null ? value : null; } 
    } 
} 

public class ObjectValue : Simple 
{ 
    [XmlAttribute("object")] 
    public string Object { 
      get { return base.Value != null ? base.Value : null; } 
      set { base.Value = value != null ? value : null; } 
    } 
} 

これはコンストラクタでシリアライズ可能な型を取るウリのようなunserializableタイプをシリアル化するために使用されるのと同じ手法です。

+0

あなたはまだプロパティを再定義しています。 –

関連する問題