Add property logging
This commit is contained in:
parent
c5f35e58d9
commit
4c02eaea75
31
Log.cs
31
Log.cs
@ -3,6 +3,8 @@ using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
//using System.Threading.Tasks;
|
||||
|
||||
namespace lib
|
||||
@ -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.
|
||||
static public void expected<T>( T value, string falseString, string trueString = "", T notExpectedValue = default(T) )
|
||||
{
|
||||
|
||||
203
Scr.cs
Normal file
203
Scr.cs
Normal 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;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -126,6 +126,7 @@
|
||||
<Compile Include="Pos.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="res\Resource.cs" />
|
||||
<Compile Include="Scr.cs" />
|
||||
<Compile Include="SerializableDictionary.cs" />
|
||||
<Compile Include="Timer.cs" />
|
||||
<Compile Include="Token.cs" />
|
||||
|
||||
Loading…
Reference in New Issue
Block a user