【发布时间】:2016-06-17 11:15:57
【问题描述】:
伙计们,
我正在尝试创建一个基类,其中的元素将存在于几种不同的类类型中。我接近解决方案,但我需要对 XML Serializer 类的输出进行更多控制。
更新
好的,根据下面的答案,我已经为 XMl 添加了 Serializable 接口,并且做得更进一步。
下面列出的是我的新测试应用程序的输出,前两个 XML 输出如我所料,第三个很接近,但它在根元素处缺少命名空间,我需要 SomeNewNameForPData 来充当 PData,即没有PData 在显示的最后一个 XML 中很明显,并且它也缺少基本请求类中的应用程序。有关预期输出,请参见最终示例。
<?xml version="1.0" encoding="utf-8"?>
<Payment1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Application="MyApp">
<Pdata Language="en">
<TimeStamp>2016-06-17T15:31:37.7767381+01:00</TimeStamp>
</Pdata>
<RequestType>Pay1</RequestType>
</Payment1>
<?xml version="1.0" encoding="utf-8"?>
<Payment2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Application="MyApp">
<Sender>ProgramClass</Sender>
<RequestType>Pay2</RequestType>
</Payment2>
<?xml version="1.0" encoding="utf-8"?>
<Payment3>
<SomeNewNameForPData>
<P_Data Language="en">
<TimeStamp>2016-06-17T15:31:37.7767381+01:00</TimeStamp>
</P_Data>
</SomeNewNameForPData>
</Payment3>
预期输出:
<?xml version="1.0" encoding="utf-8"?>
<Payment3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Application="MyApp">
<SomeNewNameForPData Language="en">
<TimeStamp>2016-06-17T15:31:37.7767381+01:00</TimeStamp>
</SomeNewNameForPData>
</Payment3>
更新代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.ComponentModel;
using System.Xml;
namespace ConsoleApplication7
{
class Program
{
static void Main(string[] args)
{
Request cp = new Payment1() { Application = "MyApp", DataField = new P_Data() { Language = "en" } };
Request cp2 = new Payment2() { Application = "MyApp", Sender = "ProgramClass" };
Request cp3 = new Payment3() { Application = "MyApp", DataField = new P_Data() { Language = "en" } };
string s1 = cp.MessageAsString();
string s2 = cp2.MessageAsString();
string s3 = cp3.MessageAsString();
Console.WriteLine(s1);
Console.WriteLine("");
Console.WriteLine(s2);
Console.WriteLine("");
Console.WriteLine(s3);
Console.ReadKey();
}
}
public class Helpers : StringWriter
{
public override Encoding Encoding
{
get { return Encoding.UTF8; }
}
}
public abstract class Request
{
[XmlAttribute()]
public string Application { get; set; }
public virtual string MessageAsString()
{
return CreateMessage();
}
private string CreateMessage()
{
return SerializeObject<Request>(this, null);
}
public static string SerializeObject<X>(X toSerialize, XmlSerializerNamespaces xmlNameSpace)
{
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
StringWriter textWriter = new StringWriter();
string utf8 = ""; ;
using (StringWriter writer = new Helpers())
{
xmlSerializer.Serialize(writer, toSerialize, xmlNameSpace);
utf8 = writer.ToString();
}
return utf8;
}
}
public abstract class RequestType1 : Request
{
public RequestType1()
{
}
[XmlIgnore()]
public abstract string RequestType { get; set; }
[XmlElement("Pdata")]
public virtual P_Data DataField { get; set; }
}
public abstract class RequestType2 : Request
{
public RequestType2()
{
}
[XmlIgnore()]
public abstract string RequestType { get; set; }
public string Sender { get; set; }
}
[Serializable]
public abstract class RequestType3 : RequestType1, IXmlSerializable
{
public RequestType3()
{
}
[XmlElement("SomeNewNameForPData")]
public override P_Data DataField { get; set; }
public System.Xml.Schema.XmlSchema GetSchema()
{
throw new NotImplementedException();
}
public void ReadXml(XmlReader reader)
{
throw new NotImplementedException();
}
public void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("SomeNewNameForPData");
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
new XmlSerializer(typeof(P_Data)).Serialize(writer, this.DataField, ns);
writer.WriteEndElement();
}
}
public class Payment1 : RequestType1
{
public Payment1()
{
}
public override string RequestType
{
get
{
return "Pay1";
}
set { }
}
}
public class Payment2 : RequestType2
{
public Payment2()
{
}
public override string RequestType
{
get
{
return "Pay2";
}
set { }
}
}
public class Payment3 : RequestType3
{
public Payment3()
{
}
public override string RequestType
{
get
{
return "Pay3";
}
set { }
}
}
public class P_Data
{
public P_Data()
{
//We need to format the datetime field
TimeStamp = DateTime.Now;
}
[XmlAttribute, DefaultValue("")]
public string Language { get; set; }
public DateTime TimeStamp { get; set; }
}
}
所以我的问题是:
当使用自定义 WriteXml 方法时,如何在 Payment3 的根元素中添加或保留命名空间,我是否还需要提供编写基类项的方法,或者我是否由于事实上,我正在使用基于类型的 XmlSerializer 对类进行序列化?
我需要 SomeNewNameForPData 来充当 PData,即没有明显的 PData
从基础请求类重新添加到应用程序中。
TIA
【问题讨论】:
-
您能解释一下为什么不想显示
<Nodes>节点吗? -
我使用 Nodes 作为 Request 或 RequestType2 中可能存在的不同类别的占位符,因此根据第 3 方的要求,将这个节点列表添加到不同的类中。在 Nodes 类中,我指定了所有可以存在的元素,这只是它们的一个子集,用于演示目的来解释问题
标签: c# .net xml inheritance serialization