Add nullable annotations and update class constructors. Improve XML deserialization handling.

This commit is contained in:
Marc Hernandez 2024-05-26 18:47:11 -07:00
parent 05656d469a
commit 4e59ae0331
6 changed files with 56 additions and 71 deletions

View File

@ -18,7 +18,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<NoWarn>$(NoWarn);SYSLIB0050;CS8981</NoWarn> <NoWarn>$(NoWarn);SYSLIB0050;CS8981; CS8632</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,4 +1,9 @@
using System; 
#nullable enable
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
@ -13,7 +18,6 @@ using lib;
namespace imm; namespace imm;
/* /*
T O D O : T O D O :
T O D O : T O D O :
@ -21,7 +25,6 @@ T O D O :
x) Add unit tests for all this. This will definitely benefit from them x) Add unit tests for all this. This will definitely benefit from them
*/ */
static public class Util static public class Util
{ {
//This can handle both Timed and Recorded //This can handle both Timed and Recorded
@ -30,7 +33,7 @@ static public class Util
[CallerFilePath] string dbgPath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0, [CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression("fn")] [CallerArgumentExpression("fn")]
string dbgExp = default ) string dbgExp = "" )
where T : Recorded<T> where T : Recorded<T>
{ {
obj = obj.Process( fn, reason, dbgName, dbgPath, dbgLine, dbgExp ); obj = obj.Process( fn, reason, dbgName, dbgPath, dbgLine, dbgExp );
@ -43,7 +46,7 @@ static public class Util
[CallerFilePath] string dbgPath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0, [CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression("fn")] [CallerArgumentExpression("fn")]
string dbgExp = default string dbgExp = ""
) )
where T : Versioned<T> where T : Versioned<T>
{ {
@ -81,7 +84,7 @@ public interface Imm
[CallerFilePath] string dbgPath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0, [CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression("next")] [CallerArgumentExpression("next")]
string dbgExp = default string dbgExp = ""
) )
{ {
return next; return next;
@ -210,7 +213,7 @@ public record class Recorded<T> : Versioned<T>, imm.Imm
} }
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
new public MetaData Meta => MetaStorage as MetaData; new public MetaData Meta => MetaStorage as MetaData ?? new MetaData();
override public T Record( override public T Record(
@ -229,7 +232,7 @@ public record class Recorded<T> : Versioned<T>, imm.Imm
[CallerFilePath] string dbgPath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0, [CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression("next")] [CallerArgumentExpression("next")]
string dbgExp = default string dbgExp = ""
) )
{ {
return ProcessWork( ( old ) => next, reason, dbgName, dbgPath, dbgLine, dbgExp ); return ProcessWork( ( old ) => next, reason, dbgName, dbgPath, dbgLine, dbgExp );
@ -242,7 +245,7 @@ public record class Recorded<T> : Versioned<T>, imm.Imm
[CallerFilePath] string dbgPath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0, [CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression("fn")] [CallerArgumentExpression("fn")]
string dbgExp = default string dbgExp = ""
) )
{ {
return ProcessWork( fn, reason, dbgName, dbgPath, dbgLine, dbgExp ); return ProcessWork( fn, reason, dbgName, dbgPath, dbgLine, dbgExp );
@ -329,7 +332,7 @@ public record class Timed<T> : Recorded<T>, imm.Imm
[CallerFilePath] string dbgPath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0, [CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression("next")] [CallerArgumentExpression("next")]
string dbgExp = default string dbgExp = ""
) )
{ {
return ProcessWork( ( old ) => next, reason, dbgName, dbgPath, dbgLine, dbgExp ); return ProcessWork( ( old ) => next, reason, dbgName, dbgPath, dbgLine, dbgExp );
@ -341,7 +344,7 @@ public record class Timed<T> : Recorded<T>, imm.Imm
[CallerFilePath] string dbgPath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0, [CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression("next")] [CallerArgumentExpression("next")]
string dbgExp = default string dbgExp = ""
) )
where U : T where U : T
{ {
@ -354,7 +357,7 @@ public record class Timed<T> : Recorded<T>, imm.Imm
[CallerFilePath] string dbgPath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0, [CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression("fn")] [CallerArgumentExpression("fn")]
string dbgExp = default string dbgExp = ""
) )
=> ProcessWork( fn, reason, dbgName, dbgPath, dbgLine, dbgExp ); => ProcessWork( fn, reason, dbgName, dbgPath, dbgLine, dbgExp );

View File

@ -1,3 +1,6 @@
#nullable enable
using System; using System;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Net.Sockets; using System.Net.Sockets;

View File

@ -77,20 +77,11 @@ public class Ref : lib.I_Serialize
[Serializable] [Serializable]
[DebuggerDisplay("Path = {path} / Res = {res}")] [DebuggerDisplay("Path = {path} / Res = {res}")]
public class Ref<T> : Ref where T : class public class Ref<T> : Ref where T : class, new()
{ {
public T? res => m_res != null ? m_res : lookup(); public T res => m_res != null ? m_res : lookup();
/* override public T lookup(
override public T? lookup()
{
m_res = Mgr.load<T>( Filename );
if( s_verboseLogging ) log.info( $"Ref.lookup {GetType().Name} {GetType().GenericTypeArguments[0]} path {Filename}" );
return m_res;
}
*/
override public T? lookup(
string reason = "", string reason = "",
[CallerMemberName] string dbgName = "", [CallerMemberName] string dbgName = "",
[CallerFilePath] string dbgPath = "", [CallerFilePath] string dbgPath = "",
@ -170,39 +161,13 @@ public class Ref<T> : Ref where T : class
[NonSerialized] [NonSerialized]
protected T m_res; protected T m_res;
} }
/*
public class RefMemory<T> : Ref<T> where T : class
{
//For serialization
public RefMemory( T res )
:
base( "{memory}" )
{
m_res = res;
}
override internal void load()
{
}
}
*/
public class Resource public class Resource
{ {
static public Mgr mgr; static public Mgr mgr;
} }
public delegate T Load<out T>( string filename ); public delegate T Load<out T>( string filename );
@ -237,9 +202,9 @@ where T : class
} }
//generic classes make a new static per generic type //generic classes make a new static per generic type
class ResCache<T> where T : class class ResCache<T> where T : class, new()
{ {
public static T s_default = default; public static T s_default = new();
public static ImmutableDictionary<string, ResourceHolder<T>> s_cache = ImmutableDictionary<string, ResourceHolder<T>>.Empty; public static ImmutableDictionary<string, ResourceHolder<T>> s_cache = ImmutableDictionary<string, ResourceHolder<T>>.Empty;
} }
@ -314,7 +279,7 @@ public class Mgr
[CallerMemberName] string dbgName = "", [CallerMemberName] string dbgName = "",
[CallerFilePath] string dbgPath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int dbgLine = 0 [CallerLineNumber] int dbgLine = 0
) where T : class ) where T : class, new()
{ {
return new Ref<T>( filename, reason, dbgName, dbgPath, dbgLine ); return new Ref<T>( filename, reason, dbgName, dbgPath, dbgLine );
} }
@ -360,11 +325,10 @@ public class Mgr
[CallerLineNumber] int dbgLine = 0, [CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression("fn")] [CallerArgumentExpression("fn")]
string dbgExp = default string dbgExp = default
) where T : class ) where T : class, new()
{ {
if( ResCache<T>.s_cache.TryGetValue( filename, out var holder ) ) if( ResCache<T>.s_cache.TryGetValue( filename, out var holder ) )
{ {
if( holder.weak.TryGetTarget( out var v ) ) if( holder.weak.TryGetTarget( out var v ) )
{ {
return v; return v;
@ -385,7 +349,7 @@ public class Mgr
return newV; return newV;
} }
static public T actualLoad<T>( string filename ) where T : class static public T actualLoad<T>( string filename ) where T : class, new()
{ {
lock(s_loading) lock(s_loading)
{ {

View File

@ -1,5 +1,6 @@
 
#nullable enable

View File

@ -1,4 +1,7 @@
using System; 
using System;
using System.IO; using System.IO;
using System.Xml; using System.Xml;
using System.Runtime.Serialization; using System.Runtime.Serialization;
@ -184,32 +187,41 @@ namespace lib
void SetFromStr( Stream stream ) void SetFromStr( Stream stream )
{ {
fromStr = stream.ToString(); fromStr = stream.ToString() ?? "{null}";
fromStr = string.IsNullOrWhiteSpace(fromStr) ? (stream as FileStream).Name : fromStr;
fromStr = string.IsNullOrWhiteSpace(fromStr) ? (stream as NetworkStream).Socket.RemoteEndPoint.ToString() : fromStr; if( stream is FileStream fs )
{
fromStr = fs.Name;
}
if( stream is NetworkStream ns )
{
fromStr = ns?.Socket?.RemoteEndPoint?.ToString() ?? $"{ns}";
}
} }
public object Deserialize( Stream stream ) public object Deserialize( Stream stream )
{ {
SetFromStr( stream ); SetFromStr( stream );
return DeserializeKnownType( stream, null ); var obj = DeserializeKnownType( stream, null );
return obj;
} }
public T Deserialize<T>( Stream stream ) => (T)DeserializeKnownType( stream, typeof( T ) ); public T? Deserialize<T>( Stream stream ) => (T)DeserializeKnownType( stream, typeof( T ) );
public object DeserializeKnownType( Stream stream, Type t ) public object? DeserializeKnownType( Stream stream, Type? t )
{ {
SetFromStr( stream ); SetFromStr( stream );
XmlTextReader reader = new( stream ); XmlTextReader reader = new( stream );
object obj = Deserialize( reader, t ); object? obj = Deserialize( reader, t );
return obj; return obj;
} }
private object Deserialize( XmlReader reader, Type t ) private object? Deserialize( XmlReader reader, Type? t )
{ {
m_alreadySerialized.Clear(); m_alreadySerialized.Clear();
m_objectID = new ObjectIDGenerator(); m_objectID = new ObjectIDGenerator();
@ -220,6 +232,8 @@ namespace lib
doc.Load( reader ); doc.Load( reader );
if( doc.DocumentElement == null ) return null;
if( t == null ) if( t == null )
return Deserialize( doc.DocumentElement ); return Deserialize( doc.DocumentElement );
@ -276,13 +290,13 @@ namespace lib
static private bool IsEnumerable( Type type ) => type.IsAssignableTo( typeof( IEnumerable ) ); static private bool IsEnumerable( Type type ) => type.IsAssignableTo( typeof( IEnumerable ) );
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*/ )
{ {
var name = mi?.Name ?? "{NOT_FOUND}"; var name = mi?.Name ?? "{NOT_FOUND}";
return Deserialize( elem, mi, type, name, existing ); return Deserialize( elem, mi, type, name, existing );
} }
private object Deserialize( XmlElement elem, MemberInfo mi, Type type, string name, object existing /*, object enclosing = null*/ ) private object Deserialize( XmlElement elem, MemberInfo? mi, Type type, string name, object? existing /*, object enclosing = null*/ )
{ {
try try
{ {