using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
using System.Xml;
using System.Xml.Schema;
#if NETFX35RTM
using System.Runtime.Serialization.Json;
#endif
namespace dasBlog.Storage{
internal static class SerializationTools<T> where T : class, new()
{
static private DataContractSerializer _serializer = new DataContractSerializer(typeof(T));
static private DataContractJsonSerializer _jsonSerializer = new DataContractJsonSerializer(typeof(T));
static private DataContractSerializer _listSerializer = new DataContractSerializer(typeof(T[]),"list","");
static private DataContractJsonSerializer _listJsonSerializer = new DataContractJsonSerializer(typeof(T[]), "list");
static private XmlDictionary _dict = new XmlDictionary();
static private XmlDictionaryReaderQuotas _quotas = new XmlDictionaryReaderQuotas();
static private XmlSchemaSet _schemas;
static private XmlDocument _factory = new XmlDocument();
static private Dictionary<string, string> _schemaNames;
static private Dictionary<string, string> _schemaQueries;
static private Dictionary<string, XmlSchemaSet> _baseUriSchemaSet;
static private string _primarySchemaTns;
static private bool _initialized=false;
class TBodyWriter : BodyWriter
{
T[] _enm = null;
T _obj = null;
WebMessageFormat _fmt;
public TBodyWriter(T obj, WebMessageFormat format)
: base(false)
{
_obj = obj;
_fmt = format;
}
public TBodyWriter(T[] enm, WebMessageFormat format)
: base(false)
{
_enm = enm;
_fmt = format;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
if (_enm != null)
{
if (_fmt == WebMessageFormat.Xml)
_listSerializer.WriteObject(writer, _enm);
else
_listJsonSerializer.WriteObject(writer, _enm);
}
else if (_obj != null)
{
if (_fmt == WebMessageFormat.Xml)
_serializer.WriteObject(writer, _obj);
else
_jsonSerializer.WriteObject(writer, _obj);
}
writer.Flush();
}
}
static SerializationTools()
{
}
private static void EnsureSchemaInit()
{
if (!_initialized)
{
XsdDataContractExporter _xe = new XsdDataContractExporter();
_xe.Export(typeof(T));
_schemas = _xe.Schemas;
_primarySchemaTns = _xe.GetSchemaTypeName(typeof(T)).Namespace;
_schemaNames = new Dictionary<string, string>();
_schemaQueries = new Dictionary<string, string>();
_baseUriSchemaSet = new Dictionary<string, XmlSchemaSet>();
int count = 1;
foreach (XmlSchema schema in _schemas.Schemas())
{
_schemaNames.Add(schema.TargetNamespace, "xsd" + count.ToString());
_schemaQueries.Add("xsd" + count.ToString(), schema.TargetNamespace);
count++;
}
_initialized = true;
}
}
internal static BodyWriter ToBodyWriter(T that, WebMessageFormat format)
{
return new TBodyWriter(that, format);
}
internal static BodyWriter ToBodyWriter(T[] that, WebMessageFormat format)
{
return new TBodyWriter(that, format);
}
internal static XmlElement ToXmlElement(IEnumerable<T> objects)
{
return _factory.ReadNode(SerializeList(objects, WebMessageFormat.Xml)) as XmlElement;
}
internal static XmlElement ToXmlElement(T that)
{
return _factory.ReadNode(Serialize(that, WebMessageFormat.Xml)) as XmlElement;
}
internal static XmlElement ToXmlElement(IEnumerable<T> objects, WebMessageFormat format)
{
return _factory.ReadNode(SerializeList(objects, format)) as XmlElement;
}
internal static XmlElement ToXmlElement(T that, WebMessageFormat format)
{
return _factory.ReadNode(Serialize(that, format)) as XmlElement;
}
internal static XmlReader Serialize(T that)
{
return Serialize(that, WebMessageFormat.Xml);
}
internal static XmlReader Serialize(T that, WebMessageFormat format)
{
var memStream = new MemoryStream();
var writer = XmlDictionaryWriter.CreateBinaryWriter(memStream, _dict);
if (format == WebMessageFormat.Xml)
_serializer.WriteObject(writer, that);
else
_jsonSerializer.WriteObject(writer, that);
writer.Flush();
memStream.Position = 0;
return XmlDictionaryReader.CreateBinaryReader(memStream, _dict, _quotas);
}
internal static XmlReader SerializeList(IEnumerable<T> objects)
{
return SerializeList(objects, WebMessageFormat.Xml);
}
internal static XmlReader SerializeList(IEnumerable<T> objects, WebMessageFormat format)
{
T[] data = new List<T>(objects).ToArray();
var memStream = new MemoryStream();
var writer = XmlDictionaryWriter.CreateBinaryWriter(memStream, _dict);
if (format == WebMessageFormat.Xml)
_listSerializer.WriteObject(writer, data);
else
_listJsonSerializer.WriteObject(writer, data);
writer.Flush();
memStream.Position = 0;
return XmlDictionaryReader.CreateBinaryReader(memStream, _dict, _quotas);
}
internal static T Deserialize(Message msg)
{
if (msg == null || msg.IsEmpty)
return null;
return Deserialize(msg.GetReaderAtBodyContents(), WebMessageFormat.Xml);
}
internal static T Deserialize(Message msg, WebMessageFormat format)
{
if (msg == null || msg.IsEmpty)
return null;
return Deserialize(msg.GetReaderAtBodyContents(), format);
}
internal static IList<T> DeserializeList(Message msg)
{
if (msg == null || msg.IsEmpty)
return new List<T>();
return DeserializeList(msg.GetReaderAtBodyContents(), WebMessageFormat.Xml);
}
internal static IList<T> DeserializeList(Message msg, WebMessageFormat format)
{
if (msg == null || msg.IsEmpty)
return new List<T>();
return DeserializeList(msg.GetReaderAtBodyContents(), format);
}
internal static T Deserialize(XmlReader reader)
{
return Deserialize(reader, WebMessageFormat.Xml);
}
internal static T Deserialize(XmlReader reader, WebMessageFormat format)
{
if (reader == null)
return null;
if ( format == WebMessageFormat.Xml)
return _serializer.ReadObject(reader) as T;
else
return _jsonSerializer.ReadObject(reader) as T;
}
internal static IList<T> DeserializeList(XmlReader reader)
{
return DeserializeList(reader, WebMessageFormat.Xml);
}
internal static IList<T> DeserializeList(XmlReader reader, WebMessageFormat format)
{
List<T> list;
if (reader == null)
return new List<T>();
if ( format == WebMessageFormat.Xml)
list = new List<T>(_listSerializer.ReadObject(reader) as T[]);
else
list = new List<T>(_listJsonSerializer.ReadObject(reader) as T[]);
return list;
}
internal static XmlSchema GetSchema(string baseUri, string schemaId)
{
XmlSchemaSet schemaSet;
EnsureSchemaInit();
if (!_baseUriSchemaSet.TryGetValue(baseUri, out schemaSet))
{
schemaSet = new XmlSchemaSet();
foreach( XmlSchema schema in _schemas.Schemas() )
{
MemoryStream memStream = new MemoryStream();
schema.Write(memStream);
memStream.Position = 0;
schemaSet.Add(XmlSchema.Read(memStream, null));
}
schemaSet.Compile();
FixSchemaLocations(schemaSet, baseUri);
_baseUriSchemaSet.Add(baseUri, schemaSet);
}
if (string.IsNullOrEmpty(schemaId))
{
foreach (XmlSchema schema in schemaSet.Schemas(_primarySchemaTns))
{
return schema;
}
}
else
{
string tns;
if (_schemaQueries.TryGetValue(schemaId, out tns))
{
foreach (XmlSchema schema in schemaSet.Schemas(tns))
{
return schema;
}
}
}
return null;
}
private static void FixSchemaLocations(XmlSchemaSet schemaSet, string baseUri)
{
foreach (XmlSchema schema in schemaSet.Schemas())
{
foreach (XmlSchemaExternal external in schema.Includes)
{
if (external != null && string.IsNullOrEmpty(external.SchemaLocation))
{
string namespaceUri = (external is XmlSchemaImport) ? ((XmlSchemaImport)external).Namespace : schema.TargetNamespace;
foreach (XmlSchema otherSchema in schemaSet.Schemas(namespaceUri ?? string.Empty))
{
if (otherSchema != schema)
{
external.SchemaLocation = baseUri + "?xsd="+_schemaNames[namespaceUri];
break;
}
}
}
}
}
}
}
}
|