本文介绍了C#中没有XMLAttributes的对象的更好XElement的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出XElement输入:

Given an XElement input:

<?xml version="1.0"?>
<Item Number="100" ItemName="TestName1" ItemId="1"/>

具有类似Item的模型:

with an Item model like:

public class Item
{
    public int ItemId { get; set; }
    public string ItemName { get; set; }
    public int? Number { get; set; }
    // public DateTime? Created {get; set;}
}

为什么要这段代码:

    public static T DeserializeObject<T>(XElement element)  where T : class, new()
    {
        try
        {
            var serializer = new XmlSerializer(typeof(T));
            var x = (T)serializer.Deserialize(element.CreateReader());

            return x;
        }
        catch
        {
            return default(T);
        }
    }

返回具有默认值的Item模型:ItemId = 0,ItemName = null,Number = null,而不是正确的值.

Returns an Item model with default values: ItemId=0, ItemName=null, Number=null instead of the correct values.

可以通过在模型[XmlAttribute("ItemName"))中添加属性来解决此问题,但我不想使用XmlAttributes.

This can be fixed by adding attributes to the model [XmlAttribute("ItemName")] but I do not want to require XmlAttributes.

向Item模型添加可为空的DateTime字段也会导致反序列化异常,即使它具有XmlAttribute.

The addition of a nullable DateTime field to the Item model also causes a deserialization exception, even if it has an XmlAttribute.

我在JSON.net中具有等效的代码,我要做的就是JToken上的p.ToObject()将其反序列化为Item对象.是否有另一种技术或反序列化器可以更好地处理此问题,而不必限定属性等,并且可以处理可为空的值. XML版本也应该如此简单.

I have the equivalent code in JSON.net where all I am doing is p.ToObject() on the JToken to deserialize it to an Item object. Is there another technique or deserializer that handles this better without having to qualify with attributes, etc. and that handles nullable values. It should be that easy for the XML version too.

请仔细考虑这个问题,因为我关闭了另一个与[重复]类似的问题,其中没有一个答案实际上满足了我的要求.

Please consider this question carefully, as I had another similar question closed as [Duplicate] where none of the answers actually covered what I was asking.

推荐答案

我最终在下面编写了类似于jToken的json解串器方法的自定义解串器.它应适用于具有简单类型属性(例如字符串,整数,日期时间等)以及这些类型的可为空的版本的基本扁平对象.它不需要XmlAttributes.

I ended up writing the custom deserializer below that is similar to the json deserializer method for jToken. It should work for basic, flat objects that have simple type properties like string, int, datetime, etc. and the nullable versions of those types. It does not require XmlAttributes.

public static T ToOject<T>(this XElement element) where T : class, new()
{
    try
    {
        T instance = new T();
        foreach (var property in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            var xattribute = element.Attribute(property.Name);
            var xelement = element.Element(property.Name);
            var propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
            var value = xattribute?.Value ?? xelement.Value;

            try
            {
                if (value != null)
                {
                    if (property.CanWrite)
                    {
                        property.SetValue(instance, Convert.ChangeType(value, propertyType));
                    }
                }
            }
            catch // (Exception ex) // If Error let the value remain default for that property type
            {
                Console.WriteLine("Not able to parse value " + value + " for type '" + property.PropertyType + "' for property " + property.Name);
            }
        }
        return instance;
    }
    catch (Exception ex)
    {
        return default(T);
    }
}

当您知道什么是什么时,您可以编写以下内容:

When you know what is, you can write the following:

   var list = xdocument.Descendants("Item")
        .Select(p => p => p.ToOject<T>())
        .ToList();

这篇关于C#中没有XMLAttributes的对象的更好XElement的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 09:14