将属性序列化为Element中的Xml属性

IUn*_*own 58 .net c# xml xml-serialization

我有以下课程:

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

    [XmlElement("SomeInfoElementName")]
    public int SomeInfo { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

哪个(当填充一些测试数据时)和使用XmlSerializer.Serialize()进行序列化会产生以下XML:

<SomeModel>
  <SomeStringElementName>testData</SomeStringElementName>
  <SomeInfoElementName>5</SomeInfoElementName>
</SomeModel>
Run Code Online (Sandbox Code Playgroud)

我需要的是:

<SomeModel>
  <SomeStringElementName Value="testData" />
  <SomeInfoElementName Value="5" />
</SomeModel>
Run Code Online (Sandbox Code Playgroud)

有没有办法在不编写自己的自定义序列化代码的情况下将其指定为属性?

Dar*_*rov 86

你需要包装类:

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; }
}
Run Code Online (Sandbox Code Playgroud)

或者如果您愿意,可采用更通用的方法:

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; }
}
Run Code Online (Sandbox Code Playgroud)

然后:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

将产生:

<?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>
Run Code Online (Sandbox Code Playgroud)

  • 是的,这给了我需要的XML模式,但它为模型增加了不必要的间接性和复杂性.现在而不仅仅是Object.SomeProperty,我有Object.SomeProperty.Value.我意识到我可能无法使用内置序列化两种方式 - 但这是问题的本质. (4认同)
  • 这就是内置串行器的工作原理. (2认同)
  • 我知道这有点旧,但我会添加从 `T` 到 `SomeInfo&lt;T&gt;` 的隐式转换操作,反之亦然。 (2认同)

Chr*_*ler 5

有点,使用XmlAttribute而不是XmlElement,但它看起来不像你想要的.它将如下所示:

<SomeModel SomeStringElementName="testData"> 
</SomeModel> 
Run Code Online (Sandbox Code Playgroud)

我能想到实现你想要的东西(本机)的唯一方法是让属性指向名为SomeStringElementName和SomeInfoElementName的对象,其中类包含一个名为"value"的getter.您可以更进一步使用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); }
    }               
}
Run Code Online (Sandbox Code Playgroud)