78

私は次のクラスを持っています:

[Serializable]
public class SomeModel
{
    [XmlElement("SomeStringElementName")]
    public string SomeString { get; set; }

    [XmlElement("SomeInfoElementName")]
    public int SomeInfo { get; set; }
}

XmlSerializer.Serialize() を使用して (いくつかのテスト データが入力された場合) シリアル化されたものは、次の XML になります。

<SomeModel>
  <SomeStringElementName>testData</SomeStringElementName>
  <SomeInfoElementName>5</SomeInfoElementName>
</SomeModel>

私が持っている必要があるのは:

<SomeModel>
  <SomeStringElementName Value="testData" />
  <SomeInfoElementName Value="5" />
</SomeModel>

独自のカスタム シリアル化コードを記述せずに、これを属性として指定する方法はありますか?

4

2 に答える 2

110

ラッパー クラスが必要になります。

public class SomeIntInfo
{
    [XmlAttribute]
    public int Value { get; set; }
}

public class SomeStringInfo
{
    [XmlAttribute]
    public string Value { get; set; }
}

public class SomeModel
{
    [XmlElement("SomeStringElementName")]
    public SomeStringInfo SomeString { get; set; }

    [XmlElement("SomeInfoElementName")]
    public SomeIntInfo SomeInfo { get; set; }
}

または、必要に応じてより一般的なアプローチ:

public class SomeInfo<T>
{
    [XmlAttribute]
    public T Value { get; set; }
}

public class SomeModel
{
    [XmlElement("SomeStringElementName")]
    public SomeInfo<string> SomeString { get; set; }

    [XmlElement("SomeInfoElementName")]
    public SomeInfo<int> SomeInfo { get; set; }
}

その後:

class Program
{
    static void Main()
    {
        var model = new SomeModel
        {
            SomeString = new SomeInfo<string> { Value = "testData" },
            SomeInfo = new SomeInfo<int> { Value = 5 }
        };
        var serializer = new XmlSerializer(model.GetType());
        serializer.Serialize(Console.Out, model);
    }
}

生成されます:

<?xml version="1.0" encoding="ibm850"?>
<SomeModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SomeStringElementName Value="testData" />
  <SomeInfoElementName Value="5" />
</SomeModel>
于 2012-07-04T14:12:48.020 に答える
8

ちょっと、 のXmlAttribute代わりに を使用しますXmlElementが、それはあなたが望むようには見えません。次のようになります。

<SomeModel SomeStringElementName="testData"> 
</SomeModel> 

あなたが望むものを(ネイティブに)達成するために私が考えることができる唯一の方法は、クラスに「値」という名前の単一のゲッターが含まれている SomeStringElementName および SomeInfoElementName という名前のオブジェクトを指すプロパティを持つことです。これをさらに一歩進めて、DataContractSerializer を使用して、ラッパー クラスをプライベートにすることができます。XmlSerializer はプライベート プロパティを読み取りません。

// TODO: make the class generic so that an int or string can be used.
[Serializable]  
public class SerializationClass
{
    public SerializationClass(string value)
    {
        this.Value = value;
    }

    [XmlAttribute("value")]
    public string Value { get; }
}


[Serializable]                     
public class SomeModel                     
{                     
    [XmlIgnore]                     
    public string SomeString { get; set; }                     

    [XmlIgnore]                      
    public int SomeInfo { get; set; }  

    [XmlElement]
    public SerializationClass SomeStringElementName
    {
        get { return new SerializationClass(this.SomeString); }
    }               
}
于 2012-07-04T14:07:38.410 に答える