将类的 Nullable double 属性序列化为 XmlText [英] Serilize a Nullable double property of class as XmlText

查看:26
本文介绍了将类的 Nullable double 属性序列化为 XmlText的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须使用以下代码进行序列化:

I have to serialize using the folowing code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace MyExample
{
    class Program
    {
    static void Main(string[] args)
    {
        MyXmlDocument document = new MyXmlDocument();

        document.MyExample.NodeA.value = "Value To Node A";
        document.MyExample.NodeB.value = "Value To Node B";
        document.MyExample.NodeC.value = 1234.567;
        document.WriteToXml(@"C:\Users\E9JR\Desktop\mydocument.xml");
        Console.Write("> Done!");
        Console.ReadKey();
    }
}

[XmlRoot(ElementName="xmlExample",IsNullable=false)]
public class XmlExample
{
    private NodeA_Elem _nodea;
    [XmlElement()]
    public NodeA_Elem NodeA
    {
        get
        {
            return _nodea;
        }
        set
        {
            _nodea = value;
        }
    }
    public bool ShouldSerializeNodeA()
    {
        return !String.IsNullOrEmpty(_nodea.value);
    }

    private NodeB_Elem _nodeb;
    [XmlElement(ElementName = "NodeB", IsNullable = false)]
    public NodeB_Elem NodeB
    {
        get
        {
            return _nodeb;
        }
        set
        {
            _nodeb = value;
        }
    }
    public bool ShouldSerializeNodeB()
    {
        return !String.IsNullOrEmpty(_nodeb.value);
    }

    private NodeC_Elem _nodec;
    [XmlElement(ElementName = "NodeC",IsNullable=false)]
    public NodeC_Elem NodeC
    {
        get
        {
            return _nodec;
        }
        set
        {
            _nodec = value;
        }
    }
    public bool ShouldSerializeNodeC()
    {
        return _nodec.value.HasValue;
    }

    public XmlExample()
    {
        _nodea = new NodeA_Elem();
        _nodeb = new NodeB_Elem();
        _nodec = new NodeC_Elem();
    }
}

public class NodeA_Elem
{
    [XmlText()]
    public string value { get; set; }
}

public class NodeB_Elem
{
    [XmlText()]
    public string value { get; set; }
}

public class NodeC_Elem
{
    [XmlText()]
    public double? value { get; set; }
}

public class MyXmlDocument
{
    private XmlExample _myexample;
    public XmlExample MyExample
    {
        get
        {
            return _myexample;
        }
        set
        {
            _myexample = value;
        }
    }

    public void WriteToXml(string path)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(XmlExample));

        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        settings.Encoding = Encoding.Unicode;

        StringWriter txtwriter = new StringWriter();
        XmlWriter xmlwtr = XmlWriter.Create(txtwriter, settings);
        serializer.Serialize(xmlwtr, MyExample);

        StreamWriter writer = new StreamWriter(path);
        writer.Write(txtwriter.ToString());

        writer.Close();
    }

    public void ReadXml(string path)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(XmlExample));

        StreamReader reader = new StreamReader(path);

        MyExample = (XmlExample)serializer.Deserialize(reader);

    }

    public MyXmlDocument()
    {
        _myexample = new XmlExample();
    }
    }
}

我正在尝试使用 value 属性作为节点的文本来序列化 NodeC,这是一个双精度值,但它不起作用,即使使用 ShouldSerialize 模式来避免序列化空节点也是如此.NodeA 和 NodeB 工作正常.我需要 NodeC 的帮助.

I'm trying to serialize NodeC using as text for the node the value property, which is a double, but it's not working, even using the ShouldSerialize pattern to avoid serialize empty nodes. NodeA and NodeB is working fine. I need help for NodeC.

推荐答案

您不能将可空双精度序列化为 XmlText.如果您查看获得的 System.InvalidOperationException 的全文,您将看到如下内容:

You can't serialize a nullable double as XmlText. If you look at the full text of the System.InvalidOperationException you are getting, you will see something like:

   InnerException: System.InvalidOperationException
        Message="Cannot serialize member 'value' of type System.Nullable`1[System.Double]. XmlAttribute/XmlText cannot be used to encode complex types."
        Source="System.Xml"
        StackTrace:
             at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
             at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
             at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)

该消息是不言自明的.来自 文档的确认XmlTextAttribute:

That message is self explanatory. Confirmation from the documentation for XmlTextAttribute:

您可以将 XmlTextAttribute 应用于返回原始类型和枚举类型的公共字段和公共读/写属性.

You can apply the XmlTextAttribute to public fields and public read/write properties that return primitive and enumeration types.

您可以将 XmlTextAttribute 应用于返回字符串数组的字段或属性.您还可以将该属性应用于 Object 类型的数组,但必须将 Type 属性设置为字符串.在这种情况下,插入到数组中的任何字符串都被序列化为 XML 文本.

You can apply the XmlTextAttribute to a field or property that returns an array of strings. You can also apply the attribute to an array of type Object but you must set the Type property to string. In that case, any strings inserted into the array are serialized as XML text.

XmlTextAttribute 还可以应用于返回 XmlNode 或 XmlNode 对象数组的字段.

The XmlTextAttribute can also be applied to a field that returns an XmlNode or an array of XmlNode objects.

要了解为什么 ShouldSerializeXXX() 在这里没有帮助,您应该了解 XmlSerializer 工作方式如下:

To understand why ShouldSerializeXXX() doesn't help here, you should understand that XmlSerializer works as follows:

  1. 第一次序列化类型时,XmlSerializer 构造函数在内部编写运行时 C# 代码以使用反射对该类型和所有引用类型的实例进行序列化和反序列化,然后编译代码并将生成的 DLL 加载到内存中.

  1. The first time you serialize a type, the XmlSerializer constructor internally writes run-time c# code to serialize and deserialize instances of the type and all referenced types using reflection, then compiles the code and loads the resulting DLL into memory.

随后,类实例的序列化和反序列化由之前创建的动态 DLL 执行.

Subsequently, serialization and deserialization of class instances are performed by the previously created dynamic DLL.

但是第 1 步无法访问该类的实例.它完全基于类型信息创建其动态库.并且,从类型信息中也无法推断出相关的ShouldSerializeXXX()方法在double?值 为空.因此,动态代码生成中止,因为无法生成将可空双精度值作为 XmlText 编写的代码.

But step 1 does not have access to the instance of the class. It creates its dynamic library based purely on type information. And, from the type information, there is no way to infer that the relevant ShouldSerializeXXX() method will return false when the double? value is null. Thus, dynamic code generation aborts, because code to write a nullable double as XmlText can't be generated.

作为一种解决方法,您可以创建一个表示双精度的字符串属性:

As a workaround, you could make a string property that represents the double:

public class NodeC_Elem
{
    [XmlIgnore]
    public double? value { get; set; }

    [XmlText]
    public string StringValue 
    {
        get
        {
            if (value == null)
                return null;
            return XmlConvert.ToString(value.Value);
        }
        set
        {
            if (value == null)
            {
                this.value = null;
                return;
            }
            this.value = XmlConvert.ToDouble(value);
        }
    }
}

这篇关于将类的 Nullable double 属性序列化为 XmlText的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆