diff --git a/cfg/Config.cs b/cfg/Config.cs index 30117c5..ea65bce 100644 --- a/cfg/Config.cs +++ b/cfg/Config.cs @@ -2,6 +2,7 @@ using System.IO; using System.Xml; using System.Reflection; +using System.Text; /* @@ -80,6 +81,8 @@ namespace lib private static Config CreateTemplate( string filename, Type t ) { + log.debug( $"Config file {filename} not found, creating template." ); + Type[] types = new Type[0]; object[] parms = new object[0]; @@ -110,22 +113,34 @@ namespace lib log.info( $"Writing out template config of type {t?.Name} in {templateFile}" ); - save( cfg, templateFile ); + saveDebug( cfg, templateFile ); } return cfg; } - static public void save( Config cfg ) + static public void saveDebug( Config cfg ) { - save( cfg, cfg.Filename ); + saveDebug( cfg, cfg.Filename ); } - static public void save( Config cfg, String filename ) + static ser.XmlCfg s_templateCfg = new() + { + POD = ser.POD.Elements, + Structure = ser.Datastructure.Tree, + Naming = ser.BackingFieldNaming.Regular, + }; + + static public void saveDebug( Config cfg, String filename ) { FileStream fs = new( filename, FileMode.Create, FileAccess.Write ); - XmlFormatter2 formatter = new(); + UTF8Encoding enc = new UTF8Encoding(true); + + byte[] info = enc.GetBytes($""); + fs.Write(info, 0, info.Length); + + ser.XmlSer formatter = new( s_templateCfg ); formatter.Serialize( fs, cfg ); @@ -153,10 +168,10 @@ namespace lib //private int _test = 0; - private static lib.XmlFormatter2Cfg s_templateCfg = new() + private static ser.XmlCfg s_templateCfg = new() { - datastructure = Datastructure.Tree, - POD = POD.Elements, + Structure = ser.Datastructure.Tree, + POD = ser.POD.Elements, }; diff --git a/res/Resource.cs b/res/Resource.cs index a50323b..b9c3a6f 100644 --- a/res/Resource.cs +++ b/res/Resource.cs @@ -211,12 +211,27 @@ internal record ResourceHolder( WeakReference WeakRef, string Name, DateTi public static class Mgr { // Internal holder for type-specific loaders. - private abstract class LoadHolder { public abstract object Load( string filename ); } + private abstract class LoadHolder + { + // @@@@ THIS IS AN ATTEMPT TO PASS CALLER INFO INTO THE RESOURCE LOADER + // Its not yet working, and maybe shouldnt exist + public abstract object Load( string filename, + string reason = "", + [CallerMemberName] string dbgName = "", + [CallerFilePath] string dbgPath = "", + [CallerLineNumber] int dbgLine = 0 + ); + } + private class LoadHolder : LoadHolder { private readonly Load _fnLoad; public LoadHolder( Load fnLoad ) { _fnLoad = fnLoad; } - public override object Load( string filename ) => _fnLoad( filename )!; + public override object Load( string filename, string reason = "", + [CallerMemberName] string dbgName = "", + [CallerFilePath] string dbgPath = "", + [CallerLineNumber] int dbgLine = 0 +) => _fnLoad( filename )!; } // Cache for resource holders (contains WeakReferences). @@ -277,8 +292,13 @@ public static class Mgr { log.debug( $"Found subtype {t.Name}, creating loader." ); var concreteLoadMethod = genericLoadMethod.MakeGenericMethod( t ); + // log.debug( $"concreteLoadMethod: {concreteLoadMethod}" ); + var loadDelegateType = typeof( Load<> ).MakeGenericType( t ); + // log.debug( $"loadDelegateType: {loadDelegateType}" ); + var loaderDelegate = Delegate.CreateDelegate( loadDelegateType, concreteLoadMethod ); + // log.debug( $"loaderDelegate: {loaderDelegate}" ); var loadHolderType = typeof( LoadHolder<> ).MakeGenericType( t ); var loadHolder = Activator.CreateInstance( loadHolderType, loaderDelegate ) as LoadHolder; @@ -298,6 +318,9 @@ public static class Mgr catch( Exception ex ) { log.error( $"Failed to create loader for subtype {t.Name}: {ex.Message}" ); + var stArr = ex.StackTrace.Split( "\n" ); + var stFirstFew = stArr.Take( Math.Min( stArr.Length, 3 ) ); + stFirstFew.ForEach( s => log.error( s ) ); } } } @@ -342,7 +365,7 @@ public static class Mgr { return cachedValue; } - + // 2. Get a lock specific to this filename and lock it. var fileLock = s_loadingLocks.GetOrAdd( filename, _ => new object() ); lock( fileLock ) @@ -407,7 +430,7 @@ public static class Mgr { if( s_loaders.TryGetValue( typeof( T ), out var loaderHolder ) ) { - var loadedObject = loaderHolder.Load( filename ); + var loadedObject = loaderHolder.Load( filename, reason, dbgName, dbgPath, dbgLine ); if( loadedObject is T value ) { var meta = (value as imm.Obj)?.Meta; diff --git a/ser/XmlSer.cs b/ser/XmlSer.cs index 273b99a..ba69168 100644 --- a/ser/XmlSer.cs +++ b/ser/XmlSer.cs @@ -290,8 +290,9 @@ public class TypeResolver } catch( Exception ex ) { - log.warn( $"Conversion failed for '{value}' to {type.Name}: {ex.Message}. Returning default." ); - return type.IsValueType ? Activator.CreateInstance( type ) : null; + object defaultVal = type.IsValueType ? Activator.CreateInstance( type )! : null!; + log.warn( $"Conversion failed for '{value}' to {type.Name}: {ex.Message}. Returning default of {defaultVal}({defaultVal.GetType().Name})." ); + return defaultVal; } } } @@ -317,6 +318,9 @@ public class PrimitiveHandler : ITypeHandler string val = elem.HasAttribute( "v" ) ? elem.GetAttribute( "v" ) : elem.InnerText; if( val == "null" ) return null; + + // So this is an interesting one. Why not use the expected type? Well, we know we have + // data in the XML, it just wont convert to what we want. return xml._resolver.ConvertSimple( val, expectedType ); } diff --git a/util/LinqExtensions.cs b/util/LinqExtensions.cs new file mode 100644 index 0000000..ba279d7 --- /dev/null +++ b/util/LinqExtensions.cs @@ -0,0 +1,17 @@ + + + + +using System; +using System.Collections.Generic; + +public static class Enumerables +{ + public static void ForEach(this IEnumerable @this, Action action) + { + foreach (T item in @this) + { + action(item); + } + } +} \ No newline at end of file