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:
Marc Hernandez 2024-04-28 15:00:48 -07:00
parent 14615e95e0
commit 0bd6b086f6
3 changed files with 103 additions and 31 deletions

View File

@ -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;

View File

@ -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 );

View File

@ -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);
}
}