x) ser/deser of collections
This commit is contained in:
parent
79b42b723e
commit
14615e95e0
@ -13,6 +13,7 @@ using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using static System.Net.WebRequestMethods;
|
||||
using System.Linq;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
|
||||
/*
|
||||
@ -103,6 +104,9 @@ namespace lib
|
||||
|
||||
public record struct TypeProxy( Func<object, string> ser, Func<string, string, object> des );
|
||||
|
||||
//public record struct CollectionCreator( Func<IEnumerable, object> FnCreate );
|
||||
|
||||
|
||||
public class XmlFormatter2Cfg: Config
|
||||
{
|
||||
public Datastructure datastructure = Datastructure.Tree;
|
||||
@ -114,6 +118,9 @@ namespace lib
|
||||
|
||||
public Dictionary<Type, TypeProxy> TypeProxy = new();
|
||||
|
||||
//public Dictionary<Type, CollectionCreator> CollectionCreator = new();
|
||||
|
||||
|
||||
public Types TypesDefault = Types.Fields;
|
||||
}
|
||||
|
||||
@ -242,7 +249,14 @@ namespace lib
|
||||
return Deserialize( elem, null, type, null );
|
||||
}
|
||||
|
||||
private bool IsEnumerable( Type type )
|
||||
{
|
||||
return type.IsAssignableTo( typeof(IEnumerable) );
|
||||
}
|
||||
|
||||
private object Deserialize( XmlElement elem, MemberInfo mi, Type type, object existing /*, object enclosing = null*/ )
|
||||
{
|
||||
try
|
||||
{
|
||||
TypeCode typeCode = Type.GetTypeCode(type);
|
||||
|
||||
@ -253,6 +267,12 @@ namespace lib
|
||||
else
|
||||
{
|
||||
if( !type.IsArray )
|
||||
{
|
||||
if( IsEnumerable(type) )
|
||||
{
|
||||
return DeserializeCollection( elem, mi, type );
|
||||
}
|
||||
else
|
||||
{
|
||||
object obj = DeserializeObject(elem, mi, type, existing);
|
||||
|
||||
@ -265,12 +285,20 @@ namespace lib
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return DeserializeArray( elem, mi, type );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
log.warn( $"Caught exception fn {mi.Name} type {type.Name} of {ex.Message}" );
|
||||
}
|
||||
|
||||
return existing;
|
||||
}
|
||||
|
||||
Type[] mm_types = new Type[1];
|
||||
private object GetDefault( Type t )
|
||||
@ -472,11 +500,13 @@ namespace lib
|
||||
|
||||
var dontAtt = childFi.GetCustomAttributes<lib.Dont>();
|
||||
|
||||
string propName = "";
|
||||
|
||||
if( name.StartsWith( "<" ) && name.EndsWith( "BackingField" ) )
|
||||
{
|
||||
var gtIndex = name.IndexOf( '>' );
|
||||
|
||||
var propName = name.Substring( 1, gtIndex - 1 );
|
||||
propName = name.Substring( 1, gtIndex - 1 );
|
||||
|
||||
var propInfo = narrowType.GetProperty( propName );
|
||||
|
||||
@ -496,6 +526,7 @@ namespace lib
|
||||
if (FilterField(filterFields, doImpls, whitelistFields, childFi as MemberInfo, name)) continue;
|
||||
|
||||
XmlElement childElem = getNamedChild(allChildren, name);
|
||||
if( childElem == null && !string.IsNullOrEmpty( propName ) ) childElem = getNamedChild( allChildren, propName );
|
||||
|
||||
if (childElem != null)
|
||||
{
|
||||
@ -609,6 +640,114 @@ namespace lib
|
||||
return list;
|
||||
}
|
||||
|
||||
private object DeserializeCollection( XmlElement elem, MemberInfo mi, Type type )
|
||||
{
|
||||
Type typeElem = typeof(object);
|
||||
|
||||
if( type.GenericTypeArguments.Length == 1 )
|
||||
{
|
||||
typeElem = type.GenericTypeArguments[0];
|
||||
}
|
||||
else if( type.GenericTypeArguments.Length == 2 )
|
||||
{
|
||||
typeElem = typeof(KeyValuePair<,>).MakeGenericType(type.GenericTypeArguments );
|
||||
}
|
||||
|
||||
|
||||
string refString = elem.GetAttribute("ref");
|
||||
int refInt = refString.Length > 0 ? Convert.ToInt32(refString) : -1;
|
||||
|
||||
XmlNodeList arrNodeList = elem.ChildNodes;
|
||||
|
||||
int length = arrNodeList.Count;
|
||||
|
||||
Array arr = createArray(typeElem, refInt, length);
|
||||
|
||||
for( int i = 0; i < arr.Length; ++i )
|
||||
{
|
||||
if( arrNodeList.Item( i ) is XmlElement )
|
||||
{
|
||||
XmlElement arrElem = (XmlElement)arrNodeList.Item(i);
|
||||
|
||||
var finalType = typeElem;
|
||||
if (arrElem.HasAttribute("_.t"))
|
||||
{
|
||||
var typename = arrElem.GetAttribute("_.t");
|
||||
finalType = FindType(typename);
|
||||
|
||||
if (finalType == null)
|
||||
finalType = typeElem;
|
||||
}
|
||||
|
||||
arr.SetValue( Deserialize( arrElem, mi, finalType, null), i );
|
||||
}
|
||||
}
|
||||
|
||||
var listType = (typeof(List<>)).MakeGenericType( typeElem );
|
||||
IList list = Activator.CreateInstance( listType ) as IList;
|
||||
|
||||
foreach( var a in arr )
|
||||
{
|
||||
list.Add( a );
|
||||
}
|
||||
|
||||
MethodInfo ?toMeth = null;
|
||||
|
||||
var typeGen = Type.MakeGenericSignatureType( type );
|
||||
|
||||
if( type == typeof(ImmutableArray<>).MakeGenericType( typeElem ) )
|
||||
{
|
||||
var genMeth = GetType().GetMethod("MakeImmutableArray", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
|
||||
toMeth = genMeth.MakeGenericMethod( typeElem );
|
||||
}
|
||||
else if( type == typeof(ImmutableDictionary<,>).MakeGenericType( typeElem.GenericTypeArguments ) )
|
||||
{
|
||||
var genMeth = GetType().GetMethod("MakeImmutableDictionary", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
|
||||
toMeth = genMeth.MakeGenericMethod( typeElem.GenericTypeArguments );
|
||||
}
|
||||
else if( type == typeof(List<>).MakeGenericType( typeElem ) )
|
||||
{
|
||||
var genMeth = GetType().GetMethod("MakeList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
|
||||
toMeth = genMeth.MakeGenericMethod( typeElem );
|
||||
}
|
||||
else if( type == typeof(Dictionary<,>).MakeGenericType( typeElem.GenericTypeArguments ) )
|
||||
{
|
||||
var genMeth = GetType().GetMethod("MakeDictionary", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
|
||||
toMeth = genMeth.MakeGenericMethod( typeElem.GenericTypeArguments );
|
||||
}
|
||||
|
||||
|
||||
var obj = toMeth?.Invoke( this, new object[1] { list } );
|
||||
|
||||
return obj;
|
||||
|
||||
}
|
||||
|
||||
private List<T> MakeList<T>( IList list )
|
||||
{
|
||||
return list as List<T>;
|
||||
}
|
||||
|
||||
private object MakeImmutableArray<T>( List<T> list )
|
||||
{
|
||||
var arr = list.ToImmutableArray();
|
||||
return arr;
|
||||
}
|
||||
|
||||
private object MakeImmutableDictionary<K,V>( List<KeyValuePair<K,V>> list )
|
||||
{
|
||||
var dict = list.ToImmutableDictionary();
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
||||
private object MakeDictionary<K,V>( List<KeyValuePair<K,V>> list )
|
||||
{
|
||||
var dict = list.ToDictionary();
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
||||
private object DeserializeArray( XmlElement elem, MemberInfo mi, Type type )
|
||||
{
|
||||
Type typeElem = type.GetElementType();
|
||||
@ -847,9 +986,16 @@ namespace lib
|
||||
else
|
||||
{
|
||||
if( !type.IsArray )
|
||||
{
|
||||
if( IsEnumerable( type ))
|
||||
{
|
||||
SerializeCollection( writer, mi, root, depth );
|
||||
}
|
||||
else
|
||||
{
|
||||
SerializeObject( writer, mi, root, depth );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SerializeArray( writer, mi, root, depth );
|
||||
@ -874,6 +1020,44 @@ namespace lib
|
||||
writer.WriteAttributeString( "v", root.ToString() );
|
||||
}
|
||||
|
||||
private void SerializeCollection( XmlWriter writer, MemberInfo mi, object root, int depth )
|
||||
{
|
||||
IEnumerable it = root as IEnumerable;
|
||||
|
||||
//Array arr = (Array)root;
|
||||
|
||||
Type typeElem = it.GetType().GenericTypeArguments[0];
|
||||
|
||||
Type type = root.GetType();
|
||||
|
||||
writer.WriteAttributeString( "_.t", getTypeName( type ) );
|
||||
|
||||
bool first;
|
||||
|
||||
long refInt = m_objectID.GetId(root, out first);
|
||||
|
||||
if( m_cfg.datastructure == Datastructure.Graph )
|
||||
{
|
||||
writer.WriteAttributeString( "ref", refInt.ToString() );
|
||||
}
|
||||
|
||||
if( first )
|
||||
{
|
||||
if( m_cfg.datastructure == Datastructure.Graph )
|
||||
{
|
||||
m_alreadySerialized[refInt] = root;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
foreach( var v in it )
|
||||
{
|
||||
Serialize( writer, mi, v, "i" + i.ToString(), depth + 1, false );
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SerializeObject( XmlWriter writer, MemberInfo mi, object root, int depth )
|
||||
{
|
||||
writer.WriteAttributeString( "_.t", getTypeName( root.GetType() ) );
|
||||
|
||||
Loading…
Reference in New Issue
Block a user