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.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
@ -74,9 +75,11 @@ public record class Versioned<T>
|
||||
|
||||
protected MetaData MetaStorage = new();
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
public MetaData Meta => MetaStorage;
|
||||
|
||||
[lib.Dont]
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
public ChangeDelegate OnChange = (x, y) => {};
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@ -197,6 +201,7 @@ public record class Timed<T> : Recorded<T>
|
||||
{
|
||||
}
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
new public MetaData Meta => MetaStorage as MetaData;
|
||||
|
||||
public TimeSpan Since => Meta.TouchedAt - Meta.Old?.Meta.TouchedAt ?? TimeSpan.MaxValue;
|
||||
|
||||
@ -12,8 +12,13 @@ using System.Threading;
|
||||
namespace res
|
||||
{
|
||||
|
||||
|
||||
using ImmDefLoad = ImmutableQueue<(string name, Ref)>;
|
||||
|
||||
public interface Res_old
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Ref : lib.I_Serialize
|
||||
@ -168,6 +173,7 @@ namespace res
|
||||
//???? Should we just always do this?
|
||||
static public void registerSub( Type baseType )
|
||||
{
|
||||
log.info( $"Registering loader for {baseType.Name}" );
|
||||
|
||||
Type[] typeParams = new Type[1];
|
||||
foreach( var mi in baseType.GetMethods() )
|
||||
@ -178,25 +184,26 @@ namespace res
|
||||
{
|
||||
foreach( var t in ass.GetTypes() )
|
||||
{
|
||||
if( t.IsSubclassOf( baseType ) )
|
||||
{
|
||||
typeParams[0] = t;
|
||||
var mi_ng = mi.MakeGenericMethod( typeParams );
|
||||
if( !baseType.IsAssignableFrom( t ) ) continue;
|
||||
|
||||
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;
|
||||
@ -325,6 +332,8 @@ namespace res
|
||||
|
||||
Mgr()
|
||||
{
|
||||
log.info( $"Creating Res.Mgr" );
|
||||
|
||||
var ts = new ThreadStart( deferredLoader );
|
||||
|
||||
m_deferredLoader = new Thread( ts );
|
||||
|
||||
@ -106,6 +106,21 @@ namespace lib
|
||||
|
||||
//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
|
||||
{
|
||||
@ -119,7 +134,9 @@ namespace lib
|
||||
public Dictionary<Type, TypeProxy> TypeProxy = new();
|
||||
|
||||
//public Dictionary<Type, CollectionCreator> CollectionCreator = new();
|
||||
|
||||
//For Serialization
|
||||
public BackingFieldNaming Naming = BackingFieldNaming.Short;
|
||||
public POD POD = POD.Attributes;
|
||||
|
||||
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*/ )
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -262,7 +285,7 @@ namespace lib
|
||||
|
||||
if( typeCode != TypeCode.Object )
|
||||
{
|
||||
return DeserializeConcrete( elem, mi, type );
|
||||
return DeserializeConcrete( elem, mi, name, type );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -315,7 +338,7 @@ namespace lib
|
||||
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 = "";
|
||||
|
||||
@ -323,6 +346,10 @@ namespace lib
|
||||
{
|
||||
val = elem.GetAttribute("v");
|
||||
}
|
||||
else if( elem.HasAttribute(name) )
|
||||
{
|
||||
val = elem.GetAttribute( name );
|
||||
}
|
||||
else
|
||||
{
|
||||
val = elem.InnerText;
|
||||
@ -523,19 +550,35 @@ namespace lib
|
||||
//This is to convert c# names that would be bad as XML tags
|
||||
name = refl.TypeToIdentifier(name);
|
||||
|
||||
// @@@ TODO This doesnt yet handle propNames!
|
||||
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 );
|
||||
string attValue = elem.GetAttribute( name );
|
||||
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 )
|
||||
{
|
||||
writer.WriteStartElement( name );
|
||||
|
||||
if( root != null )
|
||||
{
|
||||
Type type = root.GetType();
|
||||
@ -981,10 +1022,17 @@ namespace lib
|
||||
|
||||
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
|
||||
{
|
||||
writer.WriteStartElement( name );
|
||||
if( !type.IsArray )
|
||||
{
|
||||
if( IsEnumerable( type ))
|
||||
@ -1004,20 +1052,26 @@ namespace lib
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteStartElement( name );
|
||||
|
||||
writer.WriteAttributeString( "v", "null" );
|
||||
}
|
||||
|
||||
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.
|
||||
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 )
|
||||
@ -1158,12 +1212,12 @@ namespace lib
|
||||
String name = childFi.Name;
|
||||
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 );
|
||||
|
||||
@ -1189,7 +1243,11 @@ namespace lib
|
||||
|
||||
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