简体   繁体   中英

Serialize all properties in a class as attributes instead of elements

I'm using XmlSerializer to serialize some classes to a XML File. Suppose I have this class:

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

if I serialize this class as it is, i'll get:

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

I'd like the properties to be serialized as xml attributes, instead of elements. I know i can achieve this by using [XmlAttribute] in each property:

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

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

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

But i have a lot of classes, with a lot of properties. Is there any way I can set this option in the class level, or event better, in my XmlSerializer class?


Based on the response given by @ulugbek-umirov, i create the following code to apply the XmlAttribute attribute to all properties in my class and base classes, in case anyone else needs it. This code is specific to my classes, because it only works with classes that starts with 'x', but If you need to adapt to your case it will easy.

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);
            }                
        }

    }

You can use instance of XmlAttributeOverrides class with XmlSerializer.

You will need a bit of reflection. The following is the basic idea how it can be done.

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;
}

Usage:

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

You may wish to add check that property is of simple type and that it is not abbreviated with XmlElement or XmlAttribute attributes.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM