Add property logging

This commit is contained in:
Marc Hernandez 2019-07-04 12:51:51 -07:00
parent c5f35e58d9
commit 4c02eaea75
3 changed files with 236 additions and 1 deletions

33
Log.cs
View File

@ -3,6 +3,8 @@ using System.IO;
using System.Diagnostics; using System.Diagnostics;
using System.Collections; using System.Collections;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Collections.Generic;
using System.Reflection;
//using System.Threading.Tasks; //using System.Threading.Tasks;
namespace lib namespace lib
@ -135,7 +137,7 @@ namespace lib
static public void log( string msg, LogType type = LogType.Debug, string cat = "unk", object obj = null ) static public void log( string msg, LogType type = LogType.Debug, string cat = "unk", object obj = null )
{ {
lock(s_log) lock( s_log )
{ {
var evt = new LogEvent( type, cat, msg, obj ); var evt = new LogEvent( type, cat, msg, obj );
@ -143,6 +145,35 @@ namespace lib
} }
} }
static public void logProps( object obj, string header, LogType type = LogType.Debug, string cat = "unk" )
{
var list = scr.GetAllProperties( obj.GetType() );
lock( s_log )
{
var evt = new LogEvent( type, cat, header, obj );
s_log.writeToAll( evt );
foreach( var pi in list )
{
try
{
var v = pi.GetValue( obj );
log( $"{pi.Name} = {v}", type, cat );
}
catch( Exception ex )
{
log( $"Exception processing {pi.Name} {ex.Message}", type, cat );
}
}
}
}
//This might seem a little odd, but the intent is that usually you wont need to set notExpectedValue. //This might seem a little odd, but the intent is that usually you wont need to set notExpectedValue.
static public void expected<T>( T value, string falseString, string trueString = "", T notExpectedValue = default(T) ) static public void expected<T>( T value, string falseString, string trueString = "", T notExpectedValue = default(T) )
{ {

203
Scr.cs Normal file
View File

@ -0,0 +1,203 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
static public class scr
{
public class PredEnumerator
{
public static PredEnumerator<T> Create<T>( IEnumerator<T> en, Predicate<T> pred )
{
return new PredEnumerator<T>( en, pred );
}
public static PredEnumerator<T> Create<T>( IEnumerable<T> en, Predicate<T> pred )
{
return new PredEnumerator<T>( en.GetEnumerator(), pred );
}
}
public class PredEnumerator<T> : PredEnumerator, IEnumerator<T>
{
public T Current => m_en.Current;
object IEnumerator.Current => m_en.Current;
public PredEnumerator( IEnumerator<T> en, Predicate<T> pred )
{
m_en = en;
m_pred = pred;
}
public bool MoveNext()
{
var success = m_en.MoveNext();
if( !success ) return false;
while( !m_pred( m_en.Current ) && (success = m_en.MoveNext()) )
{
}
return success;
}
public void Reset()
{
m_en.Reset();
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose( bool disposing )
{
if( !disposedValue )
{
if( disposing )
{
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~MyEnumerator()
// {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose( true );
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
IEnumerator<T> m_en;
Predicate<T> m_pred;
}
public class PredEnumerable<T> : IEnumerable<T>
{
public PredEnumerable( PredEnumerator<T> en )
{
m_en = en;
}
public IEnumerator<T> GetEnumerator()
{
return m_en;
}
IEnumerator IEnumerable.GetEnumerator()
{
return m_en;
}
PredEnumerator<T> m_en;
}
public static void GetAllFields( Type t, List<FieldInfo> list )
{
var fieldArr = t.GetFields(
BindingFlags.DeclaredOnly |
BindingFlags.NonPublic |
BindingFlags.Public |
BindingFlags.Instance);
var en = PredEnumerator.Create<FieldInfo>( fieldArr.AsEnumerable<FieldInfo>(), fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null );
list.AddRange( new PredEnumerable<FieldInfo>( en ) );
if( t.BaseType != null && t.BaseType != typeof( object ) )
{
GetAllFields( t.BaseType, list );
}
}
public static ImmutableList<FieldInfo> GetAllFields( Type t )
{
if( s_fieldCache.TryGetValue( t, out var info ) )
return info;
var list = new List<FieldInfo>();
GetAllFields( t, list );
var immList = list.ToImmutableList();
s_fieldCache = s_fieldCache.Add( t, immList );
return immList;
}
public static void GetAllProperties( Type t, List<PropertyInfo> list )
{
var propArr = t.GetProperties(
BindingFlags.DeclaredOnly |
BindingFlags.NonPublic |
BindingFlags.Public |
BindingFlags.Instance);
var en = PredEnumerator.Create<PropertyInfo>( propArr.AsEnumerable<PropertyInfo>(), fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null );
list.AddRange( new PredEnumerable<PropertyInfo>( en ) );
if( t.BaseType != null && t.BaseType != typeof( object ) )
{
GetAllProperties( t.BaseType, list );
}
}
public static ImmutableList<PropertyInfo> GetAllProperties( Type t )
{
if( s_propCache.TryGetValue( t, out var info ) ) return info;
var list = new List<PropertyInfo>();
GetAllProperties( t, list );
var immList = list.ToImmutableList();
s_propCache = s_propCache.Add( t, immList );
return immList;
}
static ImmutableDictionary<Type, ImmutableList<FieldInfo>> s_fieldCache = ImmutableDictionary<Type, ImmutableList<FieldInfo>>.Empty;
static ImmutableDictionary<Type, ImmutableList<PropertyInfo>> s_propCache = ImmutableDictionary<Type, ImmutableList<PropertyInfo>>.Empty;
}

View File

@ -126,6 +126,7 @@
<Compile Include="Pos.cs" /> <Compile Include="Pos.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="res\Resource.cs" /> <Compile Include="res\Resource.cs" />
<Compile Include="Scr.cs" />
<Compile Include="SerializableDictionary.cs" /> <Compile Include="SerializableDictionary.cs" />
<Compile Include="Timer.cs" /> <Compile Include="Timer.cs" />
<Compile Include="Token.cs" /> <Compile Include="Token.cs" />