x) Remove some Meta things from the debug view
x) Better resource handling. Resources can be subclasses of interfaces now x) Add a bit of logging x) Add ser/deser to and from Attributes x) If saving backing fields, use short names (ie the prop name) x) Default to attributes and shortnames
This commit is contained in:
parent
14615e95e0
commit
0bd6b086f6
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@ -74,9 +75,11 @@ public record class Versioned<T>
|
|||||||
|
|
||||||
protected MetaData MetaStorage = new();
|
protected MetaData MetaStorage = new();
|
||||||
|
|
||||||
|
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||||
public MetaData Meta => MetaStorage;
|
public MetaData Meta => MetaStorage;
|
||||||
|
|
||||||
[lib.Dont]
|
[lib.Dont]
|
||||||
|
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||||
public ChangeDelegate OnChange = (x, y) => {};
|
public ChangeDelegate OnChange = (x, y) => {};
|
||||||
|
|
||||||
public T Process( Func<T, T> fn, string reason = "" )
|
public T Process( Func<T, T> fn, string reason = "" )
|
||||||
@ -120,6 +123,7 @@ public record class Recorded<T> : Versioned<T>
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||||
new public MetaData Meta => MetaStorage as MetaData;
|
new public MetaData Meta => MetaStorage as MetaData;
|
||||||
|
|
||||||
|
|
||||||
@ -197,6 +201,7 @@ public record class Timed<T> : Recorded<T>
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||||
new public MetaData Meta => MetaStorage as MetaData;
|
new public MetaData Meta => MetaStorage as MetaData;
|
||||||
|
|
||||||
public TimeSpan Since => Meta.TouchedAt - Meta.Old?.Meta.TouchedAt ?? TimeSpan.MaxValue;
|
public TimeSpan Since => Meta.TouchedAt - Meta.Old?.Meta.TouchedAt ?? TimeSpan.MaxValue;
|
||||||
|
|||||||
@ -12,8 +12,13 @@ using System.Threading;
|
|||||||
namespace res
|
namespace res
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
using ImmDefLoad = ImmutableQueue<(string name, Ref)>;
|
using ImmDefLoad = ImmutableQueue<(string name, Ref)>;
|
||||||
|
|
||||||
|
public interface Res_old
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class Ref : lib.I_Serialize
|
public class Ref : lib.I_Serialize
|
||||||
@ -168,6 +173,7 @@ namespace res
|
|||||||
//???? Should we just always do this?
|
//???? Should we just always do this?
|
||||||
static public void registerSub( Type baseType )
|
static public void registerSub( Type baseType )
|
||||||
{
|
{
|
||||||
|
log.info( $"Registering loader for {baseType.Name}" );
|
||||||
|
|
||||||
Type[] typeParams = new Type[1];
|
Type[] typeParams = new Type[1];
|
||||||
foreach( var mi in baseType.GetMethods() )
|
foreach( var mi in baseType.GetMethods() )
|
||||||
@ -178,25 +184,26 @@ namespace res
|
|||||||
{
|
{
|
||||||
foreach( var t in ass.GetTypes() )
|
foreach( var t in ass.GetTypes() )
|
||||||
{
|
{
|
||||||
if( t.IsSubclassOf( baseType ) )
|
if( !baseType.IsAssignableFrom( t ) ) continue;
|
||||||
{
|
|
||||||
typeParams[0] = t;
|
|
||||||
var mi_ng = mi.MakeGenericMethod( typeParams );
|
|
||||||
|
|
||||||
var loadGenType = typeof(Load<>);
|
log.debug( $"Making a lodaer for {t.Name}" );
|
||||||
|
|
||||||
var loadType = loadGenType.MakeGenericType( t );
|
typeParams[0] = t;
|
||||||
|
var mi_ng = mi.MakeGenericMethod( typeParams );
|
||||||
|
|
||||||
var loader = Delegate.CreateDelegate( loadType, mi_ng );
|
var loadGenType = typeof(Load<>);
|
||||||
|
|
||||||
var lhGenType = typeof(LoadHolder<>);
|
var loadType = loadGenType.MakeGenericType( t );
|
||||||
|
|
||||||
var lhType = lhGenType.MakeGenericType( t );
|
var loader = Delegate.CreateDelegate( loadType, mi_ng );
|
||||||
|
|
||||||
var lh = Activator.CreateInstance( lhType, loader ) as LoadHolder;
|
var lhGenType = typeof(LoadHolder<>);
|
||||||
|
|
||||||
ImmutableInterlocked.TryAdd( ref Resource.mgr.m_loaders, t, lh );
|
var lhType = lhGenType.MakeGenericType( t );
|
||||||
}
|
|
||||||
|
var lh = Activator.CreateInstance( lhType, loader ) as LoadHolder;
|
||||||
|
|
||||||
|
ImmutableInterlocked.TryAdd( ref Resource.mgr.m_loaders, t, lh );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -325,6 +332,8 @@ namespace res
|
|||||||
|
|
||||||
Mgr()
|
Mgr()
|
||||||
{
|
{
|
||||||
|
log.info( $"Creating Res.Mgr" );
|
||||||
|
|
||||||
var ts = new ThreadStart( deferredLoader );
|
var ts = new ThreadStart( deferredLoader );
|
||||||
|
|
||||||
m_deferredLoader = new Thread( ts );
|
m_deferredLoader = new Thread( ts );
|
||||||
|
|||||||
@ -106,6 +106,21 @@ namespace lib
|
|||||||
|
|
||||||
//public record struct CollectionCreator( Func<IEnumerable, object> FnCreate );
|
//public record struct CollectionCreator( Func<IEnumerable, object> FnCreate );
|
||||||
|
|
||||||
|
//These 2 enums are for serialization
|
||||||
|
public enum BackingFieldNaming
|
||||||
|
{
|
||||||
|
Invalid,
|
||||||
|
Short, //Use the prop name
|
||||||
|
Regular,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum POD
|
||||||
|
{
|
||||||
|
Invalid,
|
||||||
|
Attributes,
|
||||||
|
Elements,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public class XmlFormatter2Cfg: Config
|
public class XmlFormatter2Cfg: Config
|
||||||
{
|
{
|
||||||
@ -119,7 +134,9 @@ namespace lib
|
|||||||
public Dictionary<Type, TypeProxy> TypeProxy = new();
|
public Dictionary<Type, TypeProxy> TypeProxy = new();
|
||||||
|
|
||||||
//public Dictionary<Type, CollectionCreator> CollectionCreator = new();
|
//public Dictionary<Type, CollectionCreator> CollectionCreator = new();
|
||||||
|
//For Serialization
|
||||||
|
public BackingFieldNaming Naming = BackingFieldNaming.Short;
|
||||||
|
public POD POD = POD.Attributes;
|
||||||
|
|
||||||
public Types TypesDefault = Types.Fields;
|
public Types TypesDefault = Types.Fields;
|
||||||
}
|
}
|
||||||
@ -255,6 +272,12 @@ namespace lib
|
|||||||
}
|
}
|
||||||
|
|
||||||
private object Deserialize( XmlElement elem, MemberInfo mi, Type type, object existing /*, object enclosing = null*/ )
|
private object Deserialize( XmlElement elem, MemberInfo mi, Type type, object existing /*, object enclosing = null*/ )
|
||||||
|
{
|
||||||
|
string name = mi?.Name ?? "{NOT_FOUND}";
|
||||||
|
return Deserialize( elem, mi, type, name, existing );
|
||||||
|
}
|
||||||
|
|
||||||
|
private object Deserialize( XmlElement elem, MemberInfo mi, Type type, string name, object existing /*, object enclosing = null*/ )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -262,7 +285,7 @@ namespace lib
|
|||||||
|
|
||||||
if( typeCode != TypeCode.Object )
|
if( typeCode != TypeCode.Object )
|
||||||
{
|
{
|
||||||
return DeserializeConcrete( elem, mi, type );
|
return DeserializeConcrete( elem, mi, name, type );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -315,7 +338,7 @@ namespace lib
|
|||||||
return default( T );
|
return default( T );
|
||||||
}
|
}
|
||||||
|
|
||||||
private object DeserializeConcrete( XmlElement elem, MemberInfo mi, Type type )
|
private object DeserializeConcrete( XmlElement elem, MemberInfo mi, string name, Type type )
|
||||||
{
|
{
|
||||||
string val = "";
|
string val = "";
|
||||||
|
|
||||||
@ -323,6 +346,10 @@ namespace lib
|
|||||||
{
|
{
|
||||||
val = elem.GetAttribute("v");
|
val = elem.GetAttribute("v");
|
||||||
}
|
}
|
||||||
|
else if( elem.HasAttribute(name) )
|
||||||
|
{
|
||||||
|
val = elem.GetAttribute( name );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = elem.InnerText;
|
val = elem.InnerText;
|
||||||
@ -523,19 +550,35 @@ namespace lib
|
|||||||
//This is to convert c# names that would be bad as XML tags
|
//This is to convert c# names that would be bad as XML tags
|
||||||
name = refl.TypeToIdentifier(name);
|
name = refl.TypeToIdentifier(name);
|
||||||
|
|
||||||
|
// @@@ TODO This doesnt yet handle propNames!
|
||||||
if (FilterField(filterFields, doImpls, whitelistFields, childFi as MemberInfo, name)) continue;
|
if (FilterField(filterFields, doImpls, whitelistFields, childFi as MemberInfo, name)) continue;
|
||||||
|
|
||||||
XmlElement childElem = getNamedChild(allChildren, name);
|
string attValue = elem.GetAttribute( name );
|
||||||
if( childElem == null && !string.IsNullOrEmpty( propName ) ) childElem = getNamedChild( allChildren, propName );
|
if( !string.IsNullOrWhiteSpace( propName ) && string.IsNullOrWhiteSpace( attValue ) ) attValue = elem.GetAttribute( propName );
|
||||||
|
|
||||||
if (childElem != null)
|
if( !string.IsNullOrWhiteSpace( attValue ) )
|
||||||
{
|
{
|
||||||
object existingObj = childFi.GetValue(obj);
|
object existingObj = childFi.GetValue(obj);
|
||||||
|
|
||||||
object childObj = Deserialize(childElem, childFi, childFi.FieldType, existingObj);
|
object childObj = DeserializeConcrete(elem, childFi, attValue, childFi.FieldType);
|
||||||
|
|
||||||
childFi.SetValue(obj, childObj);
|
childFi.SetValue(obj, childObj);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XmlElement childElem = getNamedChild(allChildren, name);
|
||||||
|
if( childElem == null && !string.IsNullOrWhiteSpace( propName ) ) childElem = getNamedChild( allChildren, propName );
|
||||||
|
|
||||||
|
if (childElem != null)
|
||||||
|
{
|
||||||
|
object existingObj = childFi.GetValue(obj);
|
||||||
|
|
||||||
|
object childObj = Deserialize(childElem, childFi, childFi.FieldType, existingObj);
|
||||||
|
|
||||||
|
childFi.SetValue(obj, childObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -971,8 +1014,6 @@ namespace lib
|
|||||||
|
|
||||||
private void Serialize( XmlWriter writer, MemberInfo mi, object root, string name, int depth, bool forceType )
|
private void Serialize( XmlWriter writer, MemberInfo mi, object root, string name, int depth, bool forceType )
|
||||||
{
|
{
|
||||||
writer.WriteStartElement( name );
|
|
||||||
|
|
||||||
if( root != null )
|
if( root != null )
|
||||||
{
|
{
|
||||||
Type type = root.GetType();
|
Type type = root.GetType();
|
||||||
@ -981,10 +1022,17 @@ namespace lib
|
|||||||
|
|
||||||
if( typeCode != TypeCode.Object )
|
if( typeCode != TypeCode.Object )
|
||||||
{
|
{
|
||||||
SerializeConcrete( writer, mi, root, forceType );
|
if( m_cfg.POD == POD.Elements || forceType ) writer.WriteStartElement( name );
|
||||||
|
|
||||||
|
SerializeConcrete( writer, mi, root, name, forceType );
|
||||||
|
|
||||||
|
if( m_cfg.POD == POD.Elements || forceType ) writer.WriteEndElement();
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
writer.WriteStartElement( name );
|
||||||
if( !type.IsArray )
|
if( !type.IsArray )
|
||||||
{
|
{
|
||||||
if( IsEnumerable( type ))
|
if( IsEnumerable( type ))
|
||||||
@ -1004,20 +1052,26 @@ namespace lib
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
writer.WriteStartElement( name );
|
||||||
|
|
||||||
writer.WriteAttributeString( "v", "null" );
|
writer.WriteAttributeString( "v", "null" );
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteEndElement();
|
writer.WriteEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SerializeConcrete( XmlWriter writer, MemberInfo mi, object root, bool forceType )
|
private void SerializeConcrete( XmlWriter writer, MemberInfo mi, object root, string name, bool forceType )
|
||||||
{
|
{
|
||||||
//TODO: Only write this out if debugging.
|
//TODO: Only write this out if debugging.
|
||||||
if( forceType )
|
if( forceType || m_cfg.POD == POD.Elements )
|
||||||
{
|
{
|
||||||
writer.WriteAttributeString( "_.t", getTypeName( root.GetType() ) );
|
if( forceType ) writer.WriteAttributeString( "_.t", getTypeName( root.GetType() ) );
|
||||||
|
writer.WriteAttributeString( "v", root.ToString() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.WriteAttributeString( name, root.ToString() );
|
||||||
}
|
}
|
||||||
writer.WriteAttributeString( "v", root.ToString() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SerializeCollection( XmlWriter writer, MemberInfo mi, object root, int depth )
|
private void SerializeCollection( XmlWriter writer, MemberInfo mi, object root, int depth )
|
||||||
@ -1158,12 +1212,12 @@ namespace lib
|
|||||||
String name = childFi.Name;
|
String name = childFi.Name;
|
||||||
var dontAtt = childFi.GetCustomAttributes<lib.Dont>();
|
var dontAtt = childFi.GetCustomAttributes<lib.Dont>();
|
||||||
|
|
||||||
|
string propName = "";
|
||||||
if( name.StartsWith( "<" ) && name.EndsWith( "BackingField" ) )
|
if( name.StartsWith( "<" ) && name.EndsWith( "BackingField" ) )
|
||||||
{
|
{
|
||||||
var gtIndex = name.IndexOf( '>' );
|
var gtIndex = name.IndexOf( '>' );
|
||||||
|
|
||||||
var propName = name.Substring( 1, gtIndex - 1 );
|
propName = name.Substring( 1, gtIndex - 1 );
|
||||||
|
|
||||||
var propInfo = narrowType.GetProperty( propName );
|
var propInfo = narrowType.GetProperty( propName );
|
||||||
|
|
||||||
@ -1189,7 +1243,11 @@ namespace lib
|
|||||||
|
|
||||||
name = refl.TypeToIdentifier(name);
|
name = refl.TypeToIdentifier(name);
|
||||||
|
|
||||||
Serialize(writer, childFi, childFi.GetValue(root), name, depth + 1, false);
|
var finalName = (m_cfg.Naming == BackingFieldNaming.Short && !string.IsNullOrEmpty( propName )) ?
|
||||||
|
propName :
|
||||||
|
name;
|
||||||
|
|
||||||
|
Serialize(writer, childFi, childFi.GetValue(root), finalName, depth + 1, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user