Massive XML changes
This commit is contained in:
parent
a27140700c
commit
8bc0aafebc
@ -180,8 +180,6 @@ static public class refl
|
|||||||
BindingFlags.Instance
|
BindingFlags.Instance
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var en = PredEnumerator.Create<PropertyInfo>( propArr.AsEnumerable<PropertyInfo>(),
|
var en = PredEnumerator.Create<PropertyInfo>( propArr.AsEnumerable<PropertyInfo>(),
|
||||||
fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null && !list.Exists( f => f.Name == fa.Name ) );
|
fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null && !list.Exists( f => f.Name == fa.Name ) );
|
||||||
|
|
||||||
|
|||||||
@ -11,85 +11,86 @@ using System.Reflection;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using static System.Net.WebRequestMethods;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
element and attribute names
|
||||||
|
- Element names are case-sensitive
|
||||||
|
- Element names must start with a letter or underscore
|
||||||
|
- Element names cannot start with the letters xml(or XML, or Xml, etc)
|
||||||
|
- Element names can contain letters, digits, hyphens, underscores, and periods
|
||||||
|
- Element names cannot contain spaces
|
||||||
|
|
||||||
* TODO
|
* TODO
|
||||||
* HUGE FLAW IN DESERIALIZATION. If you deser into something it resets everything to default values
|
* x) Add the ability for correctly named attributes to be able to fill in classes
|
||||||
* This didnt matter before when I did full things, but it matters now
|
* x)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace lib
|
namespace lib
|
||||||
{
|
{
|
||||||
|
|
||||||
public class AttDocumentSubclasses : Attribute
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface I_Serialize
|
public interface I_Serialize
|
||||||
{
|
{
|
||||||
void OnSerialize();
|
void OnSerialize();
|
||||||
void OnDeserialize( object enclosing );
|
void OnDeserialize( object enclosing );
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InstanceAttribute : Attribute
|
[Flags]
|
||||||
|
public enum Types
|
||||||
{
|
{
|
||||||
|
Fields = 0b_0001,
|
||||||
|
Props = 0b_0010,
|
||||||
|
Implied= 0b_0100,
|
||||||
|
|
||||||
|
None = 0b_000,
|
||||||
|
Default = Fields,
|
||||||
|
All = Fields | Props,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropertiesAttribute : Attribute
|
public class Ser : Attribute
|
||||||
{
|
{
|
||||||
|
public Types Types { get; set; } = Types.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class WLChildAttributes : Attribute
|
||||||
|
|
||||||
public class WhitelistAttribute : Attribute
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class WhitelistFieldsAttribute : Attribute
|
|
||||||
{
|
{
|
||||||
public string[] Values { get; private set; }
|
public string[] Values { get; private set; }
|
||||||
|
|
||||||
public WhitelistFieldsAttribute( params string[] values )
|
public WLChildAttributes( params string[] values )
|
||||||
{
|
{
|
||||||
this.Values = values;
|
this.Values = values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WhitelistPropsAttribute : Attribute
|
public class WLChildFieldsAttribute : WLChildAttributes
|
||||||
{
|
{
|
||||||
public string[] Values { get; private set; }
|
public WLChildFieldsAttribute( params string[] values ) : base( values ) { }
|
||||||
|
}
|
||||||
|
|
||||||
public WhitelistPropsAttribute( params string[] values )
|
public class WLChildPropsAttribute : WLChildAttributes
|
||||||
{
|
{
|
||||||
this.Values = values;
|
public WLChildPropsAttribute( params string[] values ) : base( values ) { }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Datastructure
|
public enum Datastructure
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
Tree,
|
Tree,
|
||||||
Full,
|
Graph,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class XmlFormatter2Cfg: Config
|
public class XmlFormatter2Cfg: Config
|
||||||
{
|
{
|
||||||
public readonly Datastructure datastructure = Datastructure.Full;
|
public readonly Datastructure datastructure = Datastructure.Graph;
|
||||||
|
|
||||||
|
public readonly int Version = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class XmlFormatter2: IFormatter
|
public class XmlFormatter2: IFormatter
|
||||||
@ -135,6 +136,8 @@ namespace lib
|
|||||||
Context = new StreamingContext( StreamingContextStates.All );
|
Context = new StreamingContext( StreamingContextStates.All );
|
||||||
|
|
||||||
m_cfg = cfg;
|
m_cfg = cfg;
|
||||||
|
|
||||||
|
log.warn( $"XML serialization is NOT fast" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -177,7 +180,7 @@ namespace lib
|
|||||||
if( t == null )
|
if( t == null )
|
||||||
return Deserialize( doc.DocumentElement );
|
return Deserialize( doc.DocumentElement );
|
||||||
|
|
||||||
return Deserialize( doc.DocumentElement, null, t );
|
return Deserialize( doc.DocumentElement, null, t, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeserializeInto<T>(Stream stream, T obj)
|
public void DeserializeInto<T>(Stream stream, T obj)
|
||||||
@ -196,7 +199,7 @@ namespace lib
|
|||||||
{
|
{
|
||||||
//lib.log.info( "object Deserialize( XmlElement elem ) {0} {1}", m_rndVal, m_alreadySerialized.Count );
|
//lib.log.info( "object Deserialize( XmlElement elem ) {0} {1}", m_rndVal, m_alreadySerialized.Count );
|
||||||
|
|
||||||
string typename = elem.HasAttribute("t") ? elem.GetAttribute("t") : elem.Name;
|
string typename = elem.HasAttribute("_.t") ? elem.GetAttribute("_.t") : elem.Name;
|
||||||
|
|
||||||
return Deserialize( elem, null, typename );
|
return Deserialize( elem, null, typename );
|
||||||
}
|
}
|
||||||
@ -223,10 +226,10 @@ namespace lib
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Deserialize( elem, null, type );
|
return Deserialize( elem, null, type, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
private object Deserialize( XmlElement elem, MemberInfo mi, Type type, object enclosing = null )
|
private object Deserialize( XmlElement elem, MemberInfo mi, Type type, object existing /*, object enclosing = null*/ )
|
||||||
{
|
{
|
||||||
TypeCode typeCode = Type.GetTypeCode(type);
|
TypeCode typeCode = Type.GetTypeCode(type);
|
||||||
|
|
||||||
@ -238,13 +241,13 @@ namespace lib
|
|||||||
{
|
{
|
||||||
if( !type.IsArray )
|
if( !type.IsArray )
|
||||||
{
|
{
|
||||||
object obj = DeserializeObject(elem, mi, type);
|
object obj = DeserializeObject(elem, mi, type, existing);
|
||||||
|
|
||||||
if( obj is I_Serialize )
|
if( obj is I_Serialize )
|
||||||
{
|
{
|
||||||
var iser = obj as I_Serialize;
|
var iser = obj as I_Serialize;
|
||||||
|
|
||||||
iser.OnDeserialize( enclosing );
|
iser.OnDeserialize( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
@ -335,11 +338,11 @@ namespace lib
|
|||||||
private Type[] mm_consType = new Type[2];
|
private Type[] mm_consType = new Type[2];
|
||||||
private object[] mm_args = new object[2];
|
private object[] mm_args = new object[2];
|
||||||
|
|
||||||
private object DeserializeObject( XmlElement elem, MemberInfo mi, Type type )
|
private object DeserializeObject( XmlElement elem, MemberInfo mi, Type type, object existing )
|
||||||
{
|
{
|
||||||
Type finalType;
|
Type finalType;
|
||||||
object obj;
|
|
||||||
GetObjectForDeser( elem, type, out finalType, out obj );
|
var obj = GetObjectForDeser( elem, type, out finalType, existing );
|
||||||
|
|
||||||
return HydrateObject( elem, mi, finalType, obj );
|
return HydrateObject( elem, mi, finalType, obj );
|
||||||
}
|
}
|
||||||
@ -378,7 +381,7 @@ namespace lib
|
|||||||
|
|
||||||
String name = node.Name;
|
String name = node.Name;
|
||||||
|
|
||||||
String childType = node.GetAttribute( "t" );
|
String childType = node.GetAttribute( "_.t" );
|
||||||
|
|
||||||
name = refl.TypeToIdentifier( name );
|
name = refl.TypeToIdentifier( name );
|
||||||
|
|
||||||
@ -431,57 +434,53 @@ namespace lib
|
|||||||
{
|
{
|
||||||
XmlNodeList allChildren = elem.ChildNodes;
|
XmlNodeList allChildren = elem.ChildNodes;
|
||||||
|
|
||||||
var doFields = true;
|
bool filterFields, filterProps, doImpls, doFields, doProps;
|
||||||
var doProperties = false;
|
HashSet<string> whitelistFields, whitelistProps;
|
||||||
|
GetFilters( mi, finalType, out filterFields, out filterProps, out doImpls, out doFields, out doProps, out whitelistFields, out whitelistProps );
|
||||||
|
|
||||||
var filterFields = mi?.GetCustomAttribute<WhitelistFieldsAttribute>() != null;
|
/*
|
||||||
var filterProps = mi?.GetCustomAttribute<WhitelistPropsAttribute>() != null;
|
List<MemberInfo> members = new();
|
||||||
|
|
||||||
HashSet<string> whitelistFields = new( mi?.GetCustomAttribute<WhitelistFieldsAttribute>()?.Values ?? new string[0] );
|
if( doFields || doImpls )
|
||||||
HashSet<string> whitelistProps = new( mi?.GetCustomAttribute<WhitelistPropsAttribute>()?.Values ?? new string[0] );
|
|
||||||
|
|
||||||
if( finalType.GetCustomAttribute<PropertiesAttribute>() != null )
|
|
||||||
{
|
{
|
||||||
doProperties = true;
|
members.AddRange( refl.GetAllFields( finalType ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( mi?.GetCustomAttribute<WhitelistPropsAttribute>() != null )
|
if( doProps || doImpls )
|
||||||
{
|
{
|
||||||
doProperties = true;
|
members.AddRange( refl.GetAllProperties( finalType ) );
|
||||||
|
|
||||||
doFields = mi?.GetCustomAttribute<WhitelistFieldsAttribute>() != null;
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if( doFields )
|
if( doFields || doImpls )
|
||||||
{
|
{
|
||||||
var fields = refl.GetAllFields( finalType );
|
var fields = refl.GetAllFields( finalType );
|
||||||
|
|
||||||
foreach( var childFi in fields )
|
foreach( FieldInfo childFi in fields )
|
||||||
{
|
{
|
||||||
|
|
||||||
String name = childFi.Name;
|
String name = childFi.Name;
|
||||||
|
|
||||||
if( filterFields && !whitelistFields.Contains( name ) ) continue;
|
//This is to convert c# names that would be bad as XML tags
|
||||||
|
|
||||||
name = refl.TypeToIdentifier( name );
|
name = refl.TypeToIdentifier( name );
|
||||||
|
|
||||||
|
if( FilterField( filterFields, doImpls, whitelistFields, childFi as MemberInfo, name ) ) continue;
|
||||||
|
|
||||||
XmlElement childElem = getNamedChild( allChildren, name );
|
XmlElement childElem = getNamedChild( allChildren, name );
|
||||||
|
|
||||||
if( childElem != null )
|
if( childElem != null )
|
||||||
{
|
{
|
||||||
object childObj = Deserialize( childElem, childFi, childFi.FieldType, obj );
|
object existingObj = childFi.GetValue( obj );
|
||||||
|
|
||||||
childFi.SetValue( obj, childObj );
|
object childObj = Deserialize( childElem, childFi, childFi.FieldType, existingObj );
|
||||||
}
|
|
||||||
else if( fields.Count == 1 )
|
|
||||||
{
|
|
||||||
object childObj = Deserialize( elem, childFi, childFi.FieldType, obj );
|
|
||||||
|
|
||||||
childFi.SetValue( obj, childObj );
|
childFi.SetValue( obj, childObj );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( doProperties )
|
|
||||||
|
if( doProps || doImpls )
|
||||||
{
|
{
|
||||||
var props = refl.GetAllProperties( finalType );
|
var props = refl.GetAllProperties( finalType );
|
||||||
|
|
||||||
@ -489,23 +488,23 @@ namespace lib
|
|||||||
{
|
{
|
||||||
String name = childPi.Name;
|
String name = childPi.Name;
|
||||||
|
|
||||||
if( filterProps && !whitelistProps.Contains( name ) ) continue;
|
|
||||||
|
|
||||||
name = refl.TypeToIdentifier( name );
|
name = refl.TypeToIdentifier( name );
|
||||||
|
|
||||||
|
if( FilterField( filterFields, doImpls, whitelistFields, childPi as MemberInfo, name ) ) continue;
|
||||||
|
|
||||||
XmlElement childElem = getNamedChild( allChildren, name );
|
XmlElement childElem = getNamedChild( allChildren, name );
|
||||||
|
|
||||||
if( childElem != null )
|
if( childElem != null )
|
||||||
{
|
{
|
||||||
object childObj = Deserialize( childElem, childPi, childPi.PropertyType, obj );
|
object existingObj = childPi.GetValue( obj );
|
||||||
|
|
||||||
|
object childObj = Deserialize( childElem, childPi, childPi.PropertyType, existingObj );
|
||||||
|
|
||||||
childPi.SetValue( obj, childObj );
|
childPi.SetValue( obj, childObj );
|
||||||
}
|
}
|
||||||
else if( props.Count == 1 )
|
else
|
||||||
{
|
{
|
||||||
object childObj = Deserialize( elem, childPi, childPi.PropertyType, obj );
|
log.warn( $"" );
|
||||||
|
|
||||||
childPi.SetValue( obj, childObj );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -516,23 +515,37 @@ namespace lib
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetObjectForDeser( XmlElement elem, Type type, out Type finalType, out object obj )
|
private static bool FilterField( bool filterFields, bool doImpls, HashSet<string> whitelistFields, MemberInfo mi, string name )
|
||||||
{
|
{
|
||||||
string refString = elem.GetAttribute( "ref" );
|
if( doImpls )
|
||||||
|
|
||||||
int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1;
|
|
||||||
|
|
||||||
finalType = type;
|
|
||||||
if( elem.HasAttribute( "t" ) )
|
|
||||||
{
|
{
|
||||||
var typename = elem.GetAttribute( "t" );
|
if( mi.GetCustomAttribute<WLChildAttributes>() == null ) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( filterFields && !whitelistFields.Contains( name ) ) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private object GetObjectForDeser( XmlElement elem, Type type, out Type finalType, object obj )
|
||||||
|
{
|
||||||
|
finalType = type;
|
||||||
|
if( elem.HasAttribute( "_.t" ) )
|
||||||
|
{
|
||||||
|
var typename = elem.GetAttribute( "_.t" );
|
||||||
finalType = FindType( typename );
|
finalType = FindType( typename );
|
||||||
|
|
||||||
if( finalType == null )
|
if( finalType == null )
|
||||||
finalType = type;
|
finalType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = createObject( finalType, refInt );
|
string refString = elem.GetAttribute( "ref" );
|
||||||
|
|
||||||
|
int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1;
|
||||||
|
|
||||||
|
obj = createObject( finalType, refInt, obj );
|
||||||
|
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
private object DeserializeList( XmlElement elem, MemberInfo mi, Type type, IList list )
|
private object DeserializeList( XmlElement elem, MemberInfo mi, Type type, IList list )
|
||||||
@ -551,7 +564,7 @@ namespace lib
|
|||||||
{
|
{
|
||||||
XmlElement arrElem = (XmlElement)arrNodeList.Item(i);
|
XmlElement arrElem = (XmlElement)arrNodeList.Item(i);
|
||||||
|
|
||||||
list.Add( Deserialize( arrElem, mi, genT[0] ) );
|
list.Add( Deserialize( arrElem, mi, genT[0], null ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,39 +591,46 @@ namespace lib
|
|||||||
XmlElement arrElem = (XmlElement)arrNodeList.Item(i);
|
XmlElement arrElem = (XmlElement)arrNodeList.Item(i);
|
||||||
|
|
||||||
var finalType = typeElem;
|
var finalType = typeElem;
|
||||||
if (arrElem.HasAttribute("t"))
|
if (arrElem.HasAttribute("_.t"))
|
||||||
{
|
{
|
||||||
var typename = arrElem.GetAttribute("t");
|
var typename = arrElem.GetAttribute("_.t");
|
||||||
finalType = FindType(typename);
|
finalType = FindType(typename);
|
||||||
|
|
||||||
if (finalType == null)
|
if (finalType == null)
|
||||||
finalType = typeElem;
|
finalType = typeElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
arr.SetValue( Deserialize( arrElem, mi, finalType), i );
|
arr.SetValue( Deserialize( arrElem, mi, finalType, null), i );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private object createObject( string typename, int refInt )
|
private object createObject( string typename, int refInt, object obj )
|
||||||
{
|
{
|
||||||
Type type = Type.GetType(typename);
|
Type type = Type.GetType(typename);
|
||||||
|
|
||||||
return createObject( type, refInt );
|
return createObject( type, refInt, obj );
|
||||||
}
|
}
|
||||||
|
|
||||||
private object createObject( Type type, int refInt )
|
private object createObject( Type type, int refInt, object existingObj )
|
||||||
{
|
{
|
||||||
TypeCode tc = Type.GetTypeCode(type);
|
TypeCode tc = Type.GetTypeCode(type);
|
||||||
|
|
||||||
if( m_cfg.datastructure == Datastructure.Full && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) )
|
if( m_cfg.datastructure == Datastructure.Graph && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) )
|
||||||
{
|
{
|
||||||
//lib.log.info( "Reusing object for {0}", refInt );
|
//lib.log.info( "Reusing object for {0}", refInt );
|
||||||
return m_alreadySerialized[refInt];
|
return m_alreadySerialized[refInt];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if( existingObj != null )
|
||||||
|
{
|
||||||
|
var existingObjType = existingObj.GetType();
|
||||||
|
|
||||||
|
if( type == existingObjType ) return existingObj;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
object obj = null;
|
object obj = null;
|
||||||
|
|
||||||
@ -640,7 +660,7 @@ namespace lib
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_cfg.datastructure == Datastructure.Full && refInt > 0 )
|
if( m_cfg.datastructure == Datastructure.Graph && refInt > 0 )
|
||||||
{
|
{
|
||||||
m_alreadySerialized[refInt] = obj;
|
m_alreadySerialized[refInt] = obj;
|
||||||
}
|
}
|
||||||
@ -660,7 +680,7 @@ namespace lib
|
|||||||
{
|
{
|
||||||
TypeCode elemTC = Type.GetTypeCode(elemType);
|
TypeCode elemTC = Type.GetTypeCode(elemType);
|
||||||
|
|
||||||
if( m_cfg.datastructure == Datastructure.Full && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) )
|
if( m_cfg.datastructure == Datastructure.Graph && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) )
|
||||||
{
|
{
|
||||||
return (Array)m_alreadySerialized[refInt];
|
return (Array)m_alreadySerialized[refInt];
|
||||||
}
|
}
|
||||||
@ -668,7 +688,7 @@ namespace lib
|
|||||||
{
|
{
|
||||||
Array arr = Array.CreateInstance(elemType, length);
|
Array arr = Array.CreateInstance(elemType, length);
|
||||||
|
|
||||||
if( m_cfg.datastructure == Datastructure.Full )
|
if( m_cfg.datastructure == Datastructure.Graph )
|
||||||
{
|
{
|
||||||
m_alreadySerialized[refInt] = arr;
|
m_alreadySerialized[refInt] = arr;
|
||||||
|
|
||||||
@ -724,11 +744,11 @@ namespace lib
|
|||||||
private void Serialize( XmlWriter writer, MemberInfo mi, object root )
|
private void Serialize( XmlWriter writer, MemberInfo mi, object root )
|
||||||
{
|
{
|
||||||
//writer.WriteStartDocument();
|
//writer.WriteStartDocument();
|
||||||
Serialize( writer, mi, root, "root", true );
|
Serialize( writer, mi, root, "root", 1, true );
|
||||||
//writer.WriteEndDocument();
|
//writer.WriteEndDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Serialize( XmlWriter writer, MemberInfo mi, object root, string name, bool forceType )
|
private void Serialize( XmlWriter writer, MemberInfo mi, object root, string name, int depth, bool forceType )
|
||||||
{
|
{
|
||||||
writer.WriteStartElement( name );
|
writer.WriteStartElement( name );
|
||||||
|
|
||||||
@ -746,11 +766,11 @@ namespace lib
|
|||||||
{
|
{
|
||||||
if( !type.IsArray )
|
if( !type.IsArray )
|
||||||
{
|
{
|
||||||
SerializeObject( writer, mi, root );
|
SerializeObject( writer, mi, root, depth );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SerializeArray( writer, mi, root );
|
SerializeArray( writer, mi, root, depth );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -767,14 +787,19 @@ namespace lib
|
|||||||
//TODO: Only write this out if debugging.
|
//TODO: Only write this out if debugging.
|
||||||
if( forceType )
|
if( forceType )
|
||||||
{
|
{
|
||||||
writer.WriteAttributeString( "t", getTypeName( root.GetType() ) );
|
writer.WriteAttributeString( "_.t", getTypeName( root.GetType() ) );
|
||||||
}
|
}
|
||||||
writer.WriteAttributeString( "v", root.ToString() );
|
writer.WriteAttributeString( "v", root.ToString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SerializeObject( XmlWriter writer, MemberInfo mi, object root )
|
private void SerializeObject( XmlWriter writer, MemberInfo mi, object root, int depth )
|
||||||
{
|
{
|
||||||
writer.WriteAttributeString( "t", getTypeName( root.GetType() ) );
|
writer.WriteAttributeString( "_.t", getTypeName( root.GetType() ) );
|
||||||
|
|
||||||
|
if(depth == 1)
|
||||||
|
{
|
||||||
|
writer.WriteAttributeString( "_.version.", $"{m_cfg.Version}" );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if( root is IList )
|
if( root is IList )
|
||||||
@ -791,7 +816,7 @@ namespace lib
|
|||||||
|
|
||||||
long refInt = m_objectID.GetId(root, out first);
|
long refInt = m_objectID.GetId(root, out first);
|
||||||
|
|
||||||
if( m_cfg.datastructure == Datastructure.Full )
|
if( m_cfg.datastructure == Datastructure.Graph )
|
||||||
{
|
{
|
||||||
writer.WriteAttributeString( "ref", refInt.ToString() );
|
writer.WriteAttributeString( "ref", refInt.ToString() );
|
||||||
|
|
||||||
@ -799,7 +824,7 @@ namespace lib
|
|||||||
|
|
||||||
if( first )
|
if( first )
|
||||||
{
|
{
|
||||||
if( m_cfg.datastructure == Datastructure.Full )
|
if( m_cfg.datastructure == Datastructure.Graph )
|
||||||
{
|
{
|
||||||
m_alreadySerialized[refInt] = root;
|
m_alreadySerialized[refInt] = root;
|
||||||
}
|
}
|
||||||
@ -830,7 +855,7 @@ namespace lib
|
|||||||
|
|
||||||
name = refl.TypeToIdentifier( name );
|
name = refl.TypeToIdentifier( name );
|
||||||
|
|
||||||
Serialize( writer, mi, serMember.Value, name, true );
|
Serialize( writer, mi, serMember.Value, name, depth, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
//var sc = new SerializationContext(
|
//var sc = new SerializationContext(
|
||||||
@ -840,30 +865,11 @@ namespace lib
|
|||||||
else
|
else
|
||||||
//*/
|
//*/
|
||||||
{
|
{
|
||||||
var doFields = true;
|
bool filterFields, filterProps, doImpls, doFields, doProps;
|
||||||
var doProperties = false;
|
HashSet<string> whitelistFields, whitelistProps;
|
||||||
|
GetFilters( mi, type, out filterFields, out filterProps, out doImpls, out doFields, out doProps, out whitelistFields, out whitelistProps );
|
||||||
|
|
||||||
var filterFields = mi?.GetCustomAttribute<WhitelistFieldsAttribute>() != null;
|
if( doFields || doImpls )
|
||||||
var filterProps = mi?.GetCustomAttribute<WhitelistPropsAttribute>() != null;
|
|
||||||
|
|
||||||
HashSet<string> whitelistFields = new( mi?.GetCustomAttribute<WhitelistFieldsAttribute>()?.Values ?? new string[0] );
|
|
||||||
HashSet<string> whitelistProps = new( mi?.GetCustomAttribute<WhitelistPropsAttribute>()?.Values ?? new string[0] );
|
|
||||||
|
|
||||||
if( type.GetCustomAttribute<PropertiesAttribute>() != null )
|
|
||||||
{
|
|
||||||
doProperties = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( mi?.GetCustomAttribute<WhitelistPropsAttribute>() != null )
|
|
||||||
{
|
|
||||||
doProperties = true;
|
|
||||||
|
|
||||||
doFields = mi?.GetCustomAttribute<WhitelistFieldsAttribute>() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//MemberInfo[] miArr = FormatterServices.GetSerializableMembers( type, Context );
|
|
||||||
|
|
||||||
if( doFields )
|
|
||||||
{
|
{
|
||||||
var fields = refl.GetAllFields( type );
|
var fields = refl.GetAllFields( type );
|
||||||
|
|
||||||
@ -871,8 +877,7 @@ namespace lib
|
|||||||
{
|
{
|
||||||
String name = childFi.Name;
|
String name = childFi.Name;
|
||||||
|
|
||||||
if( filterFields && !whitelistFields.Contains( name ) ) continue;
|
if( FilterField( filterFields, doImpls, whitelistFields, childFi as MemberInfo, name ) ) continue;
|
||||||
|
|
||||||
|
|
||||||
object[] objs = childFi.GetCustomAttributes( typeof( NonSerializedAttribute ), true );
|
object[] objs = childFi.GetCustomAttributes( typeof( NonSerializedAttribute ), true );
|
||||||
|
|
||||||
@ -885,11 +890,11 @@ namespace lib
|
|||||||
|
|
||||||
name = refl.TypeToIdentifier( name );
|
name = refl.TypeToIdentifier( name );
|
||||||
|
|
||||||
Serialize( writer, childFi, childFi.GetValue( root ), name, false );
|
Serialize( writer, childFi, childFi.GetValue( root ), name, depth + 1, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( doProperties )
|
if( doProps || doImpls )
|
||||||
{
|
{
|
||||||
var props = refl.GetAllProperties( type );
|
var props = refl.GetAllProperties( type );
|
||||||
|
|
||||||
@ -897,7 +902,7 @@ namespace lib
|
|||||||
{
|
{
|
||||||
String name = childPi.Name;
|
String name = childPi.Name;
|
||||||
|
|
||||||
if( filterProps && !whitelistProps.Contains( name ) ) continue;
|
if( FilterField( filterProps, doImpls, whitelistProps, childPi as MemberInfo, name ) ) continue;
|
||||||
|
|
||||||
object[] objs = childPi.GetCustomAttributes( typeof( NonSerializedAttribute ), true );
|
object[] objs = childPi.GetCustomAttributes( typeof( NonSerializedAttribute ), true );
|
||||||
|
|
||||||
@ -908,7 +913,7 @@ namespace lib
|
|||||||
|
|
||||||
name = refl.TypeToIdentifier( name );
|
name = refl.TypeToIdentifier( name );
|
||||||
|
|
||||||
Serialize( writer, childPi, childPi.GetValue( root ), name, false );
|
Serialize( writer, childPi, childPi.GetValue( root ), name, depth + 1, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -916,7 +921,24 @@ namespace lib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SerializeArray( XmlWriter writer, MemberInfo mi, object root )
|
private static void GetFilters( MemberInfo mi, Type type, out bool filterFields, out bool filterProps, out bool doImpls, out bool doFields, out bool doProps, out HashSet<string> whitelistFields, out HashSet<string> whitelistProps )
|
||||||
|
{
|
||||||
|
var custWLFields = mi?.GetCustomAttribute<WLChildFieldsAttribute>();
|
||||||
|
var custWLProps = mi?.GetCustomAttribute<WLChildPropsAttribute>();
|
||||||
|
|
||||||
|
filterFields = custWLFields != null;
|
||||||
|
filterProps = custWLProps != null;
|
||||||
|
|
||||||
|
var typesTodo = type.GetCustomAttribute<Ser>()?.Types ?? Types.None;
|
||||||
|
|
||||||
|
doImpls = typesTodo.HasFlag( Types.Implied );
|
||||||
|
doFields = filterFields || typesTodo.HasFlag( Types.Fields );
|
||||||
|
doProps = filterProps || typesTodo.HasFlag( Types.Props );
|
||||||
|
whitelistFields = new( custWLFields?.Values ?? new string[0] );
|
||||||
|
whitelistProps = new( custWLProps?.Values ?? new string[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SerializeArray( XmlWriter writer, MemberInfo mi, object root, int depth )
|
||||||
{
|
{
|
||||||
Array arr = (Array)root;
|
Array arr = (Array)root;
|
||||||
|
|
||||||
@ -924,20 +946,20 @@ namespace lib
|
|||||||
|
|
||||||
Type type = root.GetType();
|
Type type = root.GetType();
|
||||||
|
|
||||||
writer.WriteAttributeString( "t", getTypeName( type ) );
|
writer.WriteAttributeString( "_.t", getTypeName( type ) );
|
||||||
|
|
||||||
bool first;
|
bool first;
|
||||||
|
|
||||||
long refInt = m_objectID.GetId(root, out first);
|
long refInt = m_objectID.GetId(root, out first);
|
||||||
|
|
||||||
if( m_cfg.datastructure == Datastructure.Full )
|
if( m_cfg.datastructure == Datastructure.Graph )
|
||||||
{
|
{
|
||||||
writer.WriteAttributeString( "ref", refInt.ToString() );
|
writer.WriteAttributeString( "ref", refInt.ToString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( first )
|
if( first )
|
||||||
{
|
{
|
||||||
if( m_cfg.datastructure == Datastructure.Full )
|
if( m_cfg.datastructure == Datastructure.Graph )
|
||||||
{
|
{
|
||||||
m_alreadySerialized[refInt] = root;
|
m_alreadySerialized[refInt] = root;
|
||||||
}
|
}
|
||||||
@ -945,7 +967,7 @@ namespace lib
|
|||||||
|
|
||||||
for( int i = 0; i < arr.Length; ++i )
|
for( int i = 0; i < arr.Length; ++i )
|
||||||
{
|
{
|
||||||
Serialize( writer, mi, arr.GetValue( i ), "i" + i.ToString(), false );
|
Serialize( writer, mi, arr.GetValue( i ), "i" + i.ToString(), depth + 1, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user