民间,
我正在尝试创建一个基类,其中的元素将存在于几种不同的类类型中。我接近解决方案,但我需要更多地控制XML Serializer类的输出。
更新
根据下面的答案,我已经为XMl添加了Serializable接口,并且还有一点了。
下面列出的是我的新测试APP的输出,我预期的前两个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
答案 0 :(得分:1)
如果在类上实现ISerializable接口,则可以控制序列化的发生方式。 https://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable(v=vs.110).aspx
答案 1 :(得分:1)
最接近的是:
<MyRequestName Sender="MyAppName" IP="123.456.7.0">
<NodeWhatever>
<BaseElement type="SomeData" LanguageCode="en" />
<BaseElement type="SomeOtherData" Amount="1000" />
</NodeWhatever>
</MyRequestName>
为什么呢?因为如果你有多个节点就没有办法重新创建原始对象,因为没有办法找出哪个基本元素属于哪个节点!
public abstract class Root
{
public string Sender { get; set; }
public string IP { get; set; }
[Persist("", ChildName = "NodeWhatever")]
public List<Node> Nodes { get; set; }
}
[PersistInclude(typeof(SomeData),typeof(SomeOtherData))]
public class Node
{
[Persist("")]
public List<BaseElement> Elements { get; set; }
}
XmlArchive serial = new XmlArchive(R.GetType());
Archive.ClassKwd = "type";
string utf8 = ""; ;
using (var mm = new MemoryStream())
{
serial.Write(mm,R,"MyRequestName");
mm.Position = 0;
using (var reader = new StreamReader(mm))
{
utf8 = reader.ReadToEnd();
}
}
Console.WriteLine(utf8);
根据您更新的问题,我可以获取此xml,不确定这是否是您想要的:
<Payment1 RequestType="Pay1" Application="MyApp">
<DataField Language="en" TimeStamp="06/17/2016 10:38:39" />
</Payment1>
<Payment2 RequestType="Pay2" Sender="ProgramClass" Application="MyApp" />
<Payment3 RequestType="Pay3" Application="MyApp">
<MyNameWhatever Language="en" TimeStamp="06/17/2016 10:38:39" />
</Payment3>
代码:
public abstract class Request
{
public string Application { get; set; }
public virtual string MessageAsString()
{
return CreateMessage();
}
private string CreateMessage()
{
return SerializeObject<Request>(this);
}
public static string SerializeObject<X>(X toSerialize)
{
var xmlSerializer = new XmlArchive(toSerialize.GetType());
Archive.Provider = CultureInfo.InvariantCulture;
string utf8 = ""; ;
using (var writer = new MemoryStream())
{
xmlSerializer.Write(writer, toSerialize);
writer.Position = 0;
var reader = new StreamReader(writer);
utf8 = reader.ReadToEnd();
}
return utf8;
}
}
public abstract class RequestType1 : Request
{
public abstract string RequestType { get; set; }
public virtual P_Data DataField { get; set; }
}
public abstract class RequestType2 : Request
{
public abstract string RequestType { get; set; }
public string Sender { get; set; }
}
public abstract class RequestType3 : RequestType1
{
[Persist("MyNameWhatever")]
public override P_Data DataField { get; set; }
}
public class Payment1 : RequestType1
{
public override string RequestType
{
get { return "Pay1"; }
set { }
}
}
public class Payment2 : RequestType2
{
public override string RequestType
{
get { return "Pay2"; }
set { }
}
}
public class Payment3 : RequestType3
{
public override string RequestType
{
get { return "Pay3"; }
set { }
}
}
public class P_Data
{
public P_Data() { TimeStamp = DateTime.Now; }
public string Language { get; set; }
public DateTime TimeStamp { get; set; }
}