【问题标题】:XmlSerializer attribute namespace for element type dt:dt namespace元素类型 dt:dt 命名空间的 XmlSerializer 属性命名空间
【发布时间】:2015-10-06 16:16:48
【问题描述】:

我正在寻找 XmlSerializer 功能以在我的输出 XML 中重新创建一些命名空间/类型信息。

所以我必须将这样的 XML 输出复制到旧的 COM 应用程序:

<Amount dt:dt="int">500</Amount>  
<StartTime dt:dt="dateTime">2014-12-30T12:00:00.000</StartTime>      

我目前这样设置我的属性的属性:

[XmlElement(ElementName = "Amount", Namespace = "urn:schemas-microsoft-com:datatypes",  
DataType = "int", Type = typeof(int))]  
public int Amount{ get; set; }  

我的 XmlSerializer 和命名空间设置如下:

XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add("dt", "urn:schemas-microsoft-com:datatypes");
s.Serialize(writer, group, namespaces);

但这只会给我这样的输出:

<dt:Amount>500</dt:Amount> 

有人知道我哪里出错了吗?

【问题讨论】:

  • 序列化在复杂的命名空间中不会一直有效。

标签: c# xml xml-serialization xml-namespaces xmlserializer


【解决方案1】:

XmlElementAttribute.Namespace 指定元素本身的命名空间,而不是元素的属性。这就是您看到dt: 前缀的原因。 DataType = "int" 在这里没有帮助你;它用于指定多态字段的类型,不会自动生成dtdata type attribute。事实上,XmlSerializer 中没有内置功能可以自动生成一个XDR data type attribute values,它属于命名空间"urn:schemas-microsoft-com:datatypes"

因此,必须手动执行此操作,使用具有必要属性的包装器结构。以下实现是类型化的而不是多态的:

public struct XdrTypeWrapper<T>
{
    class XdrTypeWrapperTypeDictionary
    {
        static XdrTypeWrapperTypeDictionary instance;

        static XdrTypeWrapperTypeDictionary() { instance = new XdrTypeWrapper<T>.XdrTypeWrapperTypeDictionary(); }

        public static XdrTypeWrapperTypeDictionary Instance { get { return instance; } }

        readonly Dictionary<Type, string> dict;

        XdrTypeWrapperTypeDictionary()
        {
            // Taken from https://msdn.microsoft.com/en-us/library/ms256121.aspx
            // https://msdn.microsoft.com/en-us/library/ms256049.aspx
            // https://msdn.microsoft.com/en-us/library/ms256088.aspx
            dict = new Dictionary<Type, string>
            {
                { typeof(string), "string" },
                { typeof(sbyte), "i1" },
                { typeof(byte), "u1" },
                { typeof(short), "i2" },
                { typeof(ushort), "u2" },
                { typeof(int), "int" }, // Could have used i4
                { typeof(uint), "ui4" },
                { typeof(long), "i8" },
                { typeof(ulong), "ui8" },
                { typeof(DateTime), "dateTime" },
                { typeof(bool), "boolean" },
                { typeof(double), "float" }, // Could have used r8
                { typeof(float), "r4" },
            };
        }

        public string DataType(Type type)
        {
            return dict[type];
        }
    }

    public XdrTypeWrapper(T value) { this.value = value; }

    public static implicit operator XdrTypeWrapper<T>(T value) { return new XdrTypeWrapper<T>(value); }

    public static implicit operator T(XdrTypeWrapper<T> wrapper) { return wrapper.Value; }

    [XmlAttribute("dt", Namespace = "urn:schemas-microsoft-com:datatypes")]
    public string DataType
    {
        get
        {
            return XdrTypeWrapperTypeDictionary.Instance.DataType(typeof(T));
        }
        set
        {
            // Do nothing.
        }
    }

    T value;

    [XmlText]
    public T Value { get { return value; } set { this.value = value; } }
}

然后在具有代理属性的类中使用它,如下所示:

public class TestClass
{
    [XmlIgnore]
    public int Amount { get; set; }

    [XmlElement("Amount")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public XdrTypeWrapper<int> XmlAmount { get { return Amount; } set { Amount = value; } }

    [XmlIgnore]
    public DateTime StartTime { get; set; }

    [XmlElement("StartTime")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public XdrTypeWrapper<DateTime> XmlStartTime { get { return StartTime; } set { StartTime = value; } }

    [XmlIgnore]
    public double Double { get; set; }

    [XmlElement("Double")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public XdrTypeWrapper<double> XmlDouble { get { return Double; } set { Double = value; } }
}

生成以下 XML:

<TestClass xmlns:dt="urn:schemas-microsoft-com:datatypes">
  <Amount dt:dt="int">101</Amount>
  <StartTime dt:dt="dateTime">2015-10-06T20:35:18.2308848+00:00</StartTime>
  <Double dt:dt="float">101.23</Double>
</TestClass>

原型fiddle.

【讨论】:

  • 哇。一个非常彻底和完整的答案,非常感谢dbc!我绝对能更好地理解 XmlSerialize 和数据类型之间的关系。小提琴的例子是锦上添花!
猜你喜欢
  • 1970-01-01
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 2022-12-31
  • 1970-01-01
  • 2012-08-01
  • 2011-08-16
  • 1970-01-01
相关资源
最近更新 更多