5

以下に示すクラスと構造体があります。xmlserializerを使用してクラスをシリアル化すると、次のようになります。

<テスト>
<テスト番号1>5</テスト番号1>
<内部テスト/>
</テスト>

Numberプロパティにセッターを指定せずに、InnerTestを適切に(できればxmlserializerを使用して)シリアル化する最も簡単な方法は何ですか?

ありがとう、ニック

public class Test 
{ 
    private InnerTest innerTest; 
    private int testNumber; 


    public Test() 
    { 
        this.innerTest = new InnerTest(); 
        this.testNumber = 5; 
    } 


    public int TestNumber1 
    { 
        get { return this.testNumber; } 
        set { this.testNumber = value;} 
    } 


    public InnerTest InnerTest 
    { 
        get { return this.innerTest; } 
        set { this.innerTest = value;} 
    } 


} 


public struct InnerTest 
{ 
    private int number; 


    public InnerTest(int number) 
    { 
        this.number = number; 
    } 
    public int Number{get { return number; }} 
} 
4

4 に答える 4

2

このシナリオで可能であれば、DataContractSerializer(。NET 3.0)を使用し、次のようなものを使用します。

[DataMember]
public int TestNumber1 
{ 
    get { return this.testNumber; } 
    set { this.testNumber = value;} 
} 

// note **not** a data-member
public InnerTest InnerTest 
{ 
    get { return this.innerTest; } 
    set { this.innerTest = value;} 
} 

[DataMember]
private int InnerTestValue
{
    get {return innerTest.Number;}
    set {innerTest = new InnerTest(value);}
}

したがって、問題を回避します。で同様のことを行うことができますが、公開XmlSerializerする必要がInnerTestValueあります(ただし、で飾ることはできますが[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]、これは理想的ではありません)。

もちろん、構造体に複数の値がある場合は...注意が必要です。もちろん、複数のシムプロパティを持つことができますが、それは少し厄介です。基本的に、[de]シリアル化と不変オブジェクト(構造体がそうであるように)は、それほどうまく混合されません。

もう1つのオプションは、全体で可変クラスを使用する別個のPOCOバージョンを維持し、2つの間で変換することです。繰り返しますが、大きなオブジェクトモデルのオプションとしてはあまり魅力的ではありません。

于 2009-01-15T08:01:50.627 に答える
2

Jon Skeet がかなり正確に言っているように、部分信頼環境で動作するように設計されているため、プロパティのパブリック get/set を使用したくない場合は、を使用する必要がありIXmlSerializableますXmlSerializer。とにかくアクセスすることはできませんでした(彼の最後の部分に答えるために-はい、そのようなシリアライザーDateTimeで明示的にサポートされている構造体もあります)。

達成しようとしているものと、使用している .NET のバージョンに応じて、公開する必要のない を使用することを検討できますDataContractSerializer(たとえばDataMemberAttribute、プライベート フィールドまたはプロパティに を配置できます)。 public getter と private setter を使用)。このシリアライザでは、XML 形式をあまり制御できません (実際には非常に制限的です。たとえば、属性をサポートすることさえできません!)。

(私は長い間、この 2 つを組み合わせたもの、つまりXmlSerializerプライベート メンバーをシリアル化する機能の柔軟性を切望してきましDataContractSerializerたが、残念ながら現時点ではありません。)

于 2009-01-15T07:40:08.923 に答える
1

自分でやったことはありませんが、IXmlSerializableインターフェースを実装するだけでよいのではないかと思います。

私が知る限り、それは構造体を可変にする必要あることを意味します-これは苦痛です。理想的には、XmlSerializerは、型に特定のシグネチャを持つコンストラクターがあるかどうかを認識する必要がありますが、それはオプションではないようです(私が見る限り)、少なくとも落胆させるために、明示的なインターフェイス実装を使用してインターフェイスを実装する価値がありますユーザーが直接使用することはできません。

他の構造体(DateTimeなど)がどのように管理するのだろうか...おそらくXmlSerializerで明示的にサポートされています。

于 2009-01-15T07:29:31.580 に答える
1

そこにあるオブジェクトで XmlSerializer を確実に使用して、期待される結果を得ることができます。

Test test = new Test { TestNumber1 = 5 };

XmlSerializer xmlSer = new XmlSerializer(typeof(Test));
MemoryStream memStm = new MemoryStream();

xmlSer.Serialize(memStm, test);

結果を確認するには、メモリ ストリームを文字列に再度読み取り、デバッガーで確認します (またはファイルに書き込みます)。

StreamReader stmR = new StreamReader(memStm);
memStm.Position = 0;
string output = stmR.ReadToEnd();

特別なことを何もしなければ、シリアル化するクラスのすべてのパブリック プロパティが XML 要素としてレンダリングされ、結果の XML に含まれます。

[XmlIgnore] などの属性がたくさんあり、必要に応じて微調整できます。

楽しみ!

于 2009-01-15T17:12:40.750 に答える