接口中的XmlAttribute / XmlElement(序列化时元素名称未更改) - 为什么?

时间:2012-04-29 22:44:42

标签: c# xml interface xml-serialization xml-attribute

当我添加" XmlAttribute / XmlElement"在将对象序列化为XML时,接口中的属性和其他100个类继承了这一点 - 为什么我输入的属性名在序列化后不会显示在XML文件中?

interface Test
{
    [XmlAttribute("Name")]
    bool PropertyName { get; set; }
}

保存文件时,显示" PropertyName"而不是"姓名"。

有没有办法使它工作,所以添加到接口的XmlAttributes的proeprty改变Value到处而不是Value,因为如果一些类继承自同一个接口,则需要很多时间来将所有这些属性添加到所有继承它的类,更改属性的名称而不是更改其中的100个更容易。

4 个答案:

答案 0 :(得分:1)

我更改了代码以更适合我的项目。我做的是这个:

    public static XmlAttributeOverrides GetXmlAttributeOverrides(Type type)
    {
        XmlAttributeOverrides overrides = new XmlAttributeOverrides();

        foreach (Type derived in ClassHandler.GetImplementedInterfaces(type))
        {

            foreach (PropertyInfo propertyInfo in derived.GetProperties())
            {
                XmlAttributeAttribute xmlAttributeAttribute = ClassHandler.GetCustomAttribute<XmlAttributeAttribute>(propertyInfo, true) as XmlAttributeAttribute;

                if (xmlAttributeAttribute == null) continue;

                XmlAttributes attr1 = new XmlAttributes();
                attr1.XmlAttribute = new XmlAttributeAttribute();
                attr1.XmlAttribute.AttributeName = xmlAttributeAttribute.AttributeName;
                overrides.Add(type, propertyInfo.Name, attr1);
            }
        }

        return overrides;
    }

我正在尝试使用属性实现接口的对象都有“[XmlAttributeAttribute(SomeName)]”。

但是,当我序列化它时会得到相同的结果。我没有从界面获取属性值。

这是我序列化的方式:

    public static void SerializeFile(String filename, object obj, bool deleteIfExists = true)
    {

        if (deleteIfExists)
        {
            FileManager.DeleteFile(filename);
        }

        Type[] extraTypes = ClassHandler.GetPropertiesTypes(obj, true);

        using (var stream = new FileStream(filename, FileMode.Create))
        {
            //XmlSerializer xmlSerialize = new XmlSerializer(obj.GetType(), extraTypes); 
            XmlSerializer xmlSerialize = new XmlSerializer(obj.GetType(), GetXmlAttributeOverrides(obj.GetType()), extraTypes, null, null);
            xmlSerialize.Serialize(stream, obj);
        }
    }

我在ClassHandler类中使用的两种方法:

    public static T GetCustomAttribute<T>(this PropertyInfo propertyInfo, bool inherit) where T : Attribute
    {
        object[] attributes = propertyInfo.GetCustomAttributes(typeof(T), inherit);

        return attributes == null || attributes.Length == 0 ? null : attributes[0] as T;
    }

    public static List<Type> GetImplementedInterfaces(Type type)
    {
        Type[] types = type.GetInterfaces();
        List<Type> lTypes = new List<Type>();

        foreach(Type t in types)
        {
            lTypes.Add(t);
        }

        return lTypes;
    }

类具有以下结构:

interface IAnimal
{
    // Properties
    // Methods
}

public abstract class Animal : IAnimal
{
    // Implements IAnimal properties and methods
    // This XmlElement gets written correctly when XML Serializing
    // Example:
    [XmlElement("AnimalAge")]
    public double Age
    {
        get { return _age; }
        set { _age = value; }
    }
}

public abstract class Bird : Animal, IAttributeWings
{
    // Implements Attributes common for all "Birds"
    // Setting "override" here gives me error
    public bool HasWings { get { return _hasWings; } set { _hasWings = value; } }
}

public class Pelican : Bird, IAttributeCanFly
{
    // Implements Attributes common for all "Pelicans"
    // Does not implement previous attribute IAttributeWings since Bird class does this
    // Setting "override" here gives me error as well
    public bool CanFly { get { return _canFly; } set { _canFly = value; } }
}

然后属性接口只有像“bool CanFly,bool hasWings”这样的属性,以及特定类别的其他属性,如本例所示。

答案 1 :(得分:1)

Deukalin,花了一些时间,并使用全面的类和接口树。

这是工作代码

    public interface ITestX
    {
        [XmlAttribute("NameX")]
        string PropertyNameX { get; set; }
    }

    public interface ITestY
    {
        [XmlAttribute("NameY")]
        string PropertyNameY { get; set; }
    }

    public interface ITestZ
    {
        [XmlAttribute("NameZ")]
        string PropertyNameZ { get; set; }
    }

    public abstract class TestC : ITestZ
    {
        public abstract string PropertyNameZ { get; set; }
    }

    public abstract class TestA : TestC, ITestX, ITestY
    {
        public abstract string PropertyNameX { get; set; }
        public abstract string PropertyNameY { get; set; }
    }

    public class TestB : TestA
    {
        public override string PropertyNameX { get; set; }
        public override string PropertyNameY  { get; set; }
        public override string PropertyNameZ { get; set; }
    }

    public static class ClassHandler
    {
        public static T GetCustomAttribute<T>(this PropertyInfo propertyInfo, bool inherit) where T : Attribute
        {
            object[] attributes = propertyInfo.GetCustomAttributes(typeof(T), inherit);

            return attributes == null || attributes.Length == 0 ? null : attributes[0] as T;
        }

        public static void GetXmlAttributeOverrides(XmlAttributeOverrides overrides, Type type)
        {
            if (type.BaseType != null)
            {
                GetXmlAttributeOverrides(overrides, type.BaseType);
            }

            foreach (Type derived in type.GetInterfaces())
            {
                foreach (PropertyInfo propertyInfo in derived.GetProperties())
                {
                    XmlAttributeAttribute xmlAttributeAttribute = ClassHandler.GetCustomAttribute<XmlAttributeAttribute>(propertyInfo, true) as XmlAttributeAttribute;

                    if (xmlAttributeAttribute == null)
                        continue;

                    XmlAttributes attr1 = new XmlAttributes();
                    attr1.XmlAttribute = new XmlAttributeAttribute();
                    attr1.XmlAttribute.AttributeName = xmlAttributeAttribute.AttributeName;
                    overrides.Add(type, propertyInfo.Name, attr1);
                }
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            XmlAttributeOverrides XmlAttributeOverrides = new XmlAttributeOverrides();
            ClassHandler.GetXmlAttributeOverrides(XmlAttributeOverrides, typeof(TestB));
            try
            {
                TestB xtest = new TestB() { PropertyNameX = "RajX", PropertyNameY = "RajY", PropertyNameZ = "RajZ" };

                StringBuilder xmlString = new StringBuilder();
                using (XmlWriter xtw = XmlTextWriter.Create(xmlString))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(TestB), XmlAttributeOverrides);
                    serializer.Serialize(xtw, xtest);

                    xtw.Flush();
                }

                Console.WriteLine(xmlString.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
}

以下是上面样本的输出

<?xml version="1.0" encoding="utf-16"?><TestB xmlns:xsi="http://www.w3.org/2001/
XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" NameZ="RajZ" Na
meX="RajX" NameY="RajY" />
Press any key to continue . . .

答案 2 :(得分:0)

某些原因它在.NET中不起作用......但我想出了这个解决方案来克服你使用 XmlAttributeOverrides 的问题。有关它的更多信息,请访问以下链接

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlattributeoverrides.aspx

您可以通过在应用程序中的某处重构/缓存此 GetXmlAttributeOverrides()方法来优化它。希望它有所帮助。

public interface ITest
{
    [XmlAttribute("Name")]
    string PropertyName { get; set; }
}

public class XTest : ITest
{
    public string PropertyName
    {
        get;
        set;
    }
}

public class Program
{
   static void Main(string[] args)
    {

        try
        {
            XTest xtest = new XTest() { PropertyName = "Raj" };

            StringBuilder xmlString = new StringBuilder();
            using (XmlWriter xtw = XmlTextWriter.Create(xmlString))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(XTest), GetXmlAttributeOverrides(typeof(XTest)));
                serializer.Serialize(xtw, xtest);

                xtw.Flush();
            }

            Console.WriteLine( xmlString.ToString());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

   public static XmlAttributeOverrides GetXmlAttributeOverrides(Type derivedType)
   {
       Type type = typeof(ITest);
       XmlAttributeOverrides overrides = new XmlAttributeOverrides();

       XmlAttributes attr = new XmlAttributes();

       foreach (PropertyInfo propertyInfo in type.GetProperties())
       {
           XmlAttributeAttribute xmlAttributeAttribute = propertyInfo.GetCustomAttribute(typeof(XmlAttributeAttribute), true) as XmlAttributeAttribute;

           if (xmlAttributeAttribute == null) continue;

           XmlAttributes attr1 = new XmlAttributes();
           attr1.XmlAttribute = new XmlAttributeAttribute();
           attr1.XmlAttribute.AttributeName = xmlAttributeAttribute.AttributeName;
           overrides.Add(derivedType, propertyInfo.Name, attr1);
       }

       return overrides;
   }
}

编辑:在您的应用中加入此扩展程序

public static class PropertyInfoEx
{
        public static T GetCustomAttribute<T>(this PropertyInfo propertyInfo, bool inherit) where T : Attribute
        {
            object[] attributes = propertyInfo.GetCustomAttributes(typeof(T), inherit);

            return attributes == null || attributes.Length == 0 ? null : attributes[0] as T;
        }

}

答案 3 :(得分:0)

在您的代码中发现了一些问题。以下是更正后的代码

public static XmlAttributeOverrides GetXmlAttributeOverrides(Type type)
{
    XmlAttributeOverrides overrides = new XmlAttributeOverrides();

    // Get all interfaces that the "type" implements (is it same as "derivedType" from previously)?
    foreach (Type derived in ClassHandler.GetImplementedInterfaces(type))
    {

        foreach (PropertyInfo propertyInfo in derived.GetProperties())
        {
            XmlAttributeAttribute xmlAttributeAttribute = ClassHandler.GetCustomAttribute<XmlAttributeAttribute>(propertyInfo, true) as XmlAttributeAttribute;

            if (xmlAttributeAttribute == null) continue;

            XmlAttributes attr1 = new XmlAttributes();
            attr1.XmlAttribute = new XmlAttributeAttribute();
            attr1.XmlAttribute.AttributeName = xmlAttributeAttribute.AttributeName;
            overrides.Add(type, propertyInfo.Name, attr1);
        }
    }

    return overrides;
}

亲自尝试。如果有效,请告诉我。