问题
I have a scenario where the Request objects are XML Serailized and sent back to a TCP server for getting processed. The serialization is done by a legacy framework. Needless to say, I can't make changes in the legacy framework.
The legacy framework, however is smart enough to realize if a request object is implementing IXmlSerializable
, in that case it takes the WriteXml method of the interface to do the serialization.
I wanted to keep maximum control of the serailzation process in my hand, therefore I wrote my RequestBase class like this:
public abstract class RequestBase : IXmlSerializable
{
[XmlElement("Environment")]
public string BaseEnvironment { get; set; }
protected RequestBase()
{
}
protected RequestBase(string environment, string image):this()
{
HaloEnvironment = environment;
}
XmlSchema IXmlSerializable.GetSchema()
{
return null;
}
void IXmlSerializable.ReadXml(XmlReader reader)
{
throw new NotImplementedException();
}
void IXmlSerializable.WriteXml(XmlWriter writer)
{
WriteXml(writer);
}
protected virtual void WriteXml(XmlWriter writer)
{
}
}
The class is as simple as one can imagine it to be. Any request object has to implement it. An example request class is like this:
[XmlRoot("MyCuteRoot")]
public class CuteRequest : RequestBase
{
public string CuteName { get; set; }
public CuteRequest ()
{
}
protected override void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("Parameters");
writer.WriteStartElement("header");
if (!string.IsNullOrWhiteSpace(BaseEnvironment ))
writer.WriteElementString("Environment", BaseEnvironment );
if (!string.IsNullOrWhiteSpace(CuteName ))
writer.WriteElementString("CuteNode", CuteName );
writer.WriteEndElement();//header
writer.WriteEndElement();//Parameters
}
}
The above class gave me the following Xml:
<MyCuteRoot>
<Parameters>
<header>
<Environment>Developer</Environment>
<CuteNode>a2</CuteNode>
</header>
</Parameters>
</MyCuteRoot>
The sun was bright till now and I was happy as this worked. Then came a scenario where the backend server started expecting something it called BulkRequest. The requests now would be integrated as collection.
I tried handling this situation with the following BulkRequest class:
public class BulkRequest:RequestBase
{
public IEnumerable<RequestBase> Requests { get; private set; }
public BulkRequest(IEnumerable<RequestBase> requests)
{
if (requests == null)
throw new ArgumentNullException("requests");
Requests = requests;
}
public BulkRequest()
{
}
protected override void WriteXml(XmlWriter writer)
{
foreach (RequestBase requestBase in Requests)
{
(requestBase as IXmlSerializable).WriteXml(writer);
}
}
}
Now this is not working. I want an xml like following:
<STPRequest>
<MyCuteRequest>
<Parameters>
<header>
<Environment>Developer</Environment>
<CuteName>a2</CuteName>
</header>
</Parameters>
</MyCuteRequest>
<MyCuteRequest>
<Parameters>
<header>
<Environment>Developer</Environment>
<CuteName>a2</CuteName>
</header>
</Parameters>
</MyCuteRequest>
</STPRequest>
this is for two CuteRequest objects present in a Bulk request. But I am getting the following xml:
<STPRequest>
<BulkRequest>
<Parameters>
<header>
<Environment>Developer</Environment>
<CuteName>a2</CuteName>
</header>
</Parameters>
<Parameters>
<header>
<Environment>Developer</Environment>
<CuteName>a2</CuteName>
</header>
</Parameters>
</BulkRequest>
</STPRequest>
The problems are two:
How to rid off the "BulkRequest" tag that is forcing itself in.
How to make the XmlRoot values of the items (i.e. MyCuteRequest) appear in the Xml (enclosing each Parameters tag.)
I thank you for your patience for having read this far. Any help will be appreciated as a couple hours of googling proved futile.
regards,
来源:https://stackoverflow.com/questions/20885455/xmlserialization-of-ixmlserializable-array