194 lines
4.7 KiB
C#
194 lines
4.7 KiB
C#
|
|
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.Serialization;
|
|
using System.Xml;
|
|
|
|
namespace ser;
|
|
|
|
|
|
// --- Primitive Handler ---
|
|
public partial class PrimitiveHandler : ser.ITypeHandler
|
|
{
|
|
public void WriteXml( XmlSer xml, XmlWriter writer, object? obj, string name, Type memberType, bool forceType )
|
|
{
|
|
if( obj == null )
|
|
{
|
|
writer.WriteStartElement( name );
|
|
writer.WriteAttributeString( "v", "null" );
|
|
writer.WriteEndElement();
|
|
return;
|
|
}
|
|
|
|
bool writeElements = xml._cfg.POD == POD.Elements || forceType || !( writer is XmlTextWriter );
|
|
if( !writeElements && writer is XmlTextWriter tw )
|
|
writeElements = tw.WriteState != WriteState.Element;
|
|
|
|
if( writeElements )
|
|
writer.WriteStartElement( name );
|
|
|
|
if( forceType || xml._cfg.POD == POD.Elements )
|
|
{
|
|
if( forceType )
|
|
writer.WriteAttributeString( "_.t", obj.GetType().FullName );
|
|
|
|
writer.WriteAttributeString( "v", obj.ToString() );
|
|
}
|
|
else
|
|
{
|
|
writer.WriteAttributeString( name, obj.ToString() );
|
|
}
|
|
|
|
if( writeElements )
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
// --- Proxy Handler ---
|
|
public partial class ProxyHandler : ITypeHandler
|
|
{
|
|
public void WriteXml( XmlSer xml, XmlWriter writer, object? obj, string name, Type memberType, bool forceType )
|
|
{
|
|
if( obj == null )
|
|
{ xml.GetHandler( typeof( object ) ).WriteXml( xml, writer, null, name, memberType, forceType ); return; }
|
|
|
|
var ti = xml._meta.Get( obj.GetType() );
|
|
if( !ti.ProxyDef.HasValue )
|
|
{ log.error( "Proxy write called without proxy def!" ); return; }
|
|
|
|
writer.WriteStartElement( name );
|
|
var proxyStr = ti.ProxyDef.Value.fnSer( obj );
|
|
|
|
// TODO: Allow arbitrary writing here
|
|
writer.WriteAttributeString( "proxy", proxyStr );
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
// --- ISerializable Handler ---
|
|
public partial class ISerializableHandler : ITypeHandler
|
|
{
|
|
public void WriteXml( XmlSer xml, XmlWriter writer, object? obj, string name, Type memberType, bool forceType )
|
|
{
|
|
if( obj == null )
|
|
{ /* Write null */ return; }
|
|
if( !( obj is ISerializable serObj ) )
|
|
{ /* Error */ return; }
|
|
|
|
writer.WriteStartElement( name );
|
|
xml.WriteTypeAttr( writer, memberType, obj.GetType() );
|
|
|
|
if( xml.HandleGraphWrite( writer, obj, out bool first ) )
|
|
{
|
|
if( first )
|
|
{
|
|
var serInfo = new SerializationInfo( obj.GetType(), new FormatterConverter() );
|
|
var context = new StreamingContext( StreamingContextStates.All );
|
|
serObj.GetObjectData( serInfo, context );
|
|
|
|
foreach( var member in serInfo )
|
|
{
|
|
xml.WriteNode( writer, member.Value, refl.TypeToIdentifier( member.Name ), member.ObjectType, true ); // Force type for ISer
|
|
}
|
|
}
|
|
}
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
// --- Collection Handler ---
|
|
public partial class CollectionHandler : ITypeHandler
|
|
{
|
|
public void WriteXml( XmlSer xml, XmlWriter writer, object? obj, string name, Type memberType, bool forceType )
|
|
{
|
|
if( obj == null )
|
|
{ /* Write null */ return; }
|
|
if( !( obj is IEnumerable collection ) )
|
|
{ /* Error */ return; }
|
|
|
|
writer.WriteStartElement( name );
|
|
xml.WriteTypeAttr( writer, memberType, obj.GetType() );
|
|
|
|
if( xml.HandleGraphWrite( writer, obj, out bool first ) )
|
|
{
|
|
if( first )
|
|
{
|
|
Type elemType = GetElementType( obj.GetType() );
|
|
int i = 0;
|
|
foreach( var item in collection )
|
|
{
|
|
xml.WriteNode( writer, item, $"i{i++}", elemType, false );
|
|
}
|
|
}
|
|
}
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
|
|
// --- Object Handler (Default/Complex) ---
|
|
public partial class ObjectHandler : ITypeHandler
|
|
{
|
|
public void WriteXml( XmlSer xml, XmlWriter writer, object? obj, string name, Type memberType, bool forceType )
|
|
{
|
|
if( obj == null )
|
|
{ /* Write null */ return; }
|
|
|
|
writer.WriteStartElement( name );
|
|
xml.WriteTypeAttr( writer, memberType, obj.GetType() );
|
|
var ti = xml._meta.Get( obj.GetType() );
|
|
|
|
if( xml.HandleGraphWrite( writer, obj, out bool first ) )
|
|
{
|
|
if( first )
|
|
{
|
|
foreach( var memberMeta in ti.Members )
|
|
{
|
|
var value = memberMeta.GetValue( obj );
|
|
if( value != null )
|
|
{
|
|
// If POD-Attribute, write attribute
|
|
if( memberMeta.IsPodAttribute )
|
|
{
|
|
try
|
|
{
|
|
writer.WriteAttributeString( memberMeta.XmlName, value.ToString() );
|
|
}
|
|
catch( Exception ex )
|
|
{
|
|
log.error( $"Writing Att {memberMeta.XmlName} = [{value}]" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
xml.WriteNode( writer, value, memberMeta.XmlName, memberMeta.Type, false );
|
|
}
|
|
catch( Exception ex )
|
|
{
|
|
log.error( $"Writing Node {memberMeta.XmlName} = [{value}]" );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
|