微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 如何为XmlElement字段定义多个名称?

我有一个客户端应用程序提供的 XML文档到我的C#应用​​程序.这是客户端如何发送XML文件
<?xml version="1.0" encoding="utf-8"?>
<SomeAccount>
    <parentId>2380983</parentId>
    <!-- more elements -->
</SomeAccount>

还有一个支持XML反序列化的C#类:

[XmlRoot]
public class SomeAccount
{
    [XmlElement("parentId")]
    public long ParentId { get; set; }
    //rest of fields...
}

但是有些客户端系统以这种方式发送XML(请注意LeParentId中的大写字母):

<?xml version="1.0" encoding="utf-8"?>
<SomeAccount>
    <LeParentId>2380983</LeParentId>
    <!-- similar for the other elements -->
</SomeAccount>

我如何使此字段(和其他人)同时支持XML名称parentId和LeParentId?

这是我目前用于XML反序列化的方法

public sealed class XmlSerializationUtil
{
    public static T Deserialize<T>(string xml)
    {
        if (xml == null)
            return default(T);
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        StringReader stringReader = new StringReader(xml);
        return (T)serializer.Deserialize(stringReader);
    }
}

我尝试在字段中添加两次[XmlElement],每个元素名称一个,但是没有起作用.

解决方法

采取2 – 让我们使用未知的元素处理事件来实现这一点(请参见下面的注释,但是有一些限制):
public class XmlSynonymDeserializer : XmlSerializer
{
    public class SynonymsAttribute : Attribute
    {
        public readonly ISet<string> Names;

        public SynonymsAttribute(params string[] names)
        {
            this.Names = new HashSet<string>(names);
        }

        public static MemberInfo GetMember(object obj,string name)
        {
            Type type = obj.GetType();

            var result = type.GetProperty(name);
            if (result != null)
                return result;

            foreach (MemberInfo member in type.GetProperties().Cast<MemberInfo>().Union(type.GetFields()))
                foreach (var attr in member.GetCustomAttributes(typeof(SynonymsAttribute),true))
                    if (attr is SynonymsAttribute && ((SynonymsAttribute)attr).Names.Contains(name))
                        return member;

            return null;
        }
    }

    public XmlSynonymDeserializer(Type type)
        : base(type)
    {
        this.UnkNownElement += this.SynonymHandler;
    }

    public XmlSynonymDeserializer(Type type,XmlRootAttribute root)
        : base(type,root)
    {
        this.UnkNownElement += this.SynonymHandler;
    }

    protected void SynonymHandler(object sender,XmlElementEventArgs e)
    {
        var member = SynonymsAttribute.GetMember(e.ObjectBeingDeserialized,e.Element.Name);
        Type memberType;

        if (member != null && member is FieldInfo)
            memberType = ((FieldInfo)member).FieldType;
        else if (member != null && member is PropertyInfo)
            memberType = ((PropertyInfo)member).PropertyType;
        else
            return;

        if (member != null)
        {
            object value;
            XmlSynonymDeserializer serializer = new XmlSynonymDeserializer(memberType,new XmlRootAttribute(e.Element.Name));
            using (System.IO.StringReader reader = new System.IO.StringReader(e.Element.OuterXml))
                value = serializer.Deserialize(reader);

            if (member is FieldInfo)
                ((FieldInfo)member).SetValue(e.ObjectBeingDeserialized,value);
            else if (member is PropertyInfo)
                ((PropertyInfo)member).SetValue(e.ObjectBeingDeserialized,value);
        }
    }
}

现在类的实际代码是:

[XmlRoot]
public class SomeAccount
{
    [XmlElement("parentId")]
    [XmlSynonymDeserializer.Synonyms("LeParentId","AnotherGreatName")]
    public long ParentId { get; set; }
    //rest of fields...
}

要反序列化,只需使用XmlSynonymDeserializer而不是常规的XmlSerializer.这应该适用于大多数基本需求.

已知限制:

>此实现仅支持具有多个名称的元素;扩展它的属性应该是微不足道的>在实体继承彼此的情况下,对属性/字段的处理的支持未被测试>此实现不检查编程错误(具有只读/常量字段/属性属性,具有相同同义词的多个成员等)

原文地址:https://www.jb51.cc/csharp/94336.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐