【问题标题】:Serialize all properties in a class as attributes instead of elements将类中的所有属性序列化为属性而不是元素
【发布时间】:2014-07-23 05:36:39
【问题描述】:

我正在使用 XmlSerializer 将一些类序列化为 XML 文件。假设我有这个类:

public class ClassToSerialize
{
    public string PropertyA { get; set; }
    public string PropertyB { get; set; }
    public string PropertyC { get; set; }
}

如果我按原样序列化这个类,我会得到:

<ClassToSerialize>
    <PropertyA>{Value}</PropertyA}
    <PropertyB>{Value}</PropertyB}
    <PropertyC>{Value}</PropertyC}
</ClassToSerialize>

我希望将属性序列化为 xml 属性,而不是元素。我知道我可以通过在每个属性中使用 [XmlAttribute] 来实现这一点:

public class ClassToSerialize
{
    [XmlAttribute]
    public string PropertyA { get; set; }

    [XmlAttribute]
    public string PropertyB { get; set; }

    [XmlAttribute]
    public string PropertyC { get; set; }
}

但是我有很多类,有很多属性。有什么方法可以在我的 XmlSerializer 类中在类级别或事件中设置此选项?


根据@ulugbek-umirov 给出的响应,我创建了以下代码以将 XmlAttribute 属性应用于我的类和基类中的所有属性,以防其他人需要它。此代码特定于我的类,因为它仅适用于以“x”开头的类,但如果您需要适应您的情况,它会很容易。

private static void GenerateXmlAttributeOverrides(XmlAttributeOverrides overrides, Type type)
{
    foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if ((propertyInfo.PropertyType.IsPrimitive || propertyInfo.PropertyType == typeof(string)))
            {
                if (!(propertyInfo.Name.EndsWith("Specified")
                    || HasAttribute(propertyInfo, typeof(XmlElementAttribute))
                    || HasAttribute(propertyInfo, typeof(XmlAttributeAttribute))))
                {
                    overrides.Add(type, propertyInfo.Name, new XmlAttributes { XmlAttribute = new XmlAttributeAttribute() });
                }
            }
            else if (propertyInfo.PropertyType.IsGenericType)
            {
                Type[] tipos = propertyInfo.PropertyType.GetGenericArguments();
                if (tipos != null && tipos.Length > 0 && tipos[0].Name.StartsWith("x"))
                    GenerateXmlAttributeOverrides(overrides, tipos[0]);
            }
            else if (propertyInfo.PropertyType.Name.StartsWith("x")) 
            {
                GenerateXmlAttributeOverrides(overrides, propertyInfo.PropertyType);
            }                
        }

    }

【问题讨论】:

    标签: c# serialization xml-serialization


    【解决方案1】:

    您可以将XmlAttributeOverrides 类的实例与 XmlSerializer 一起使用。

    您需要进行一些反思。以下是它的基本思路。

    static XmlAttributeOverrides GenerateXmlAttributeOverrides(Type type)
    {
        XmlAttributeOverrides xmlAttributeOverrides = new XmlAttributeOverrides();
        foreach(PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            xmlAttributeOverrides.Add(type, propertyInfo.Name, new XmlAttributes { XmlAttribute = new XmlAttributeAttribute() });
        return xmlAttributeOverrides;
    }
    

    用法:

    XmlAttributeOverrides overrides = GenerateXmlAttributeOverrides(typeof(ClassToSerialize));
    XmlSerializer serializer = new XmlSerializer(typeof(ClassToSerialize), overrides);
    

    您可能希望添加检查属性是否为简单类型,并且该属性未使用XmlElementXmlAttribute 属性缩写。

    static XmlAttributeOverrides GenerateXmlAttributeOverrides(Type type)
    {
        XmlAttributeOverrides xmlAttributeOverrides = new XmlAttributeOverrides();
        foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if ((propertyInfo.PropertyType.IsPrimitive || propertyInfo.PropertyType == typeof(string)) &&
                !propertyInfo.GetCustomAttributes().Any(a => a.GetType() == typeof(XmlElementAttribute) ||
                                                             a.GetType() == typeof(XmlAttributeAttribute)))
                xmlAttributeOverrides.Add(type, propertyInfo.Name, new XmlAttributes { XmlAttribute = new XmlAttributeAttribute() });
        }
        return xmlAttributeOverrides;
    }
    

    【讨论】:

    • 看起来很有趣。我会尽快尝试。
    • 谢谢,这真的很有帮助,我会更正 propertyInfo.GetType() 返回 PropertyInfo 对象的类型,而不是它所代表的属性的类型。为此,我使用了 propertyInfo.PropertyType。
    猜你喜欢
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多