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; using System.Threading.Tasks; static public class refl { public class PredEnumerator { public static PredEnumerator Create( IEnumerator en, Predicate pred ) { return new PredEnumerator( en, pred ); } public static PredEnumerator Create( IEnumerable en, Predicate pred ) { return new PredEnumerator( en.GetEnumerator(), pred ); } } public class PredEnumerator : PredEnumerator, IEnumerator { public T Current => m_en.Current; object IEnumerator.Current => m_en.Current; public PredEnumerator( IEnumerator en, Predicate 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 m_en; Predicate m_pred; } public class PredEnumerable : IEnumerable { public PredEnumerable( PredEnumerator en ) { m_en = en; } public IEnumerator GetEnumerator() { return m_en; } IEnumerator IEnumerable.GetEnumerator() { return m_en; } PredEnumerator m_en; } public static string PrettyName( FieldInfo fi ) { var name = fi.Name; if( name[0] != '<' ) return name; var gtIndex = name.IndexOf( '>' ); name = name.Substring( 1, gtIndex - 1 ); return name; } public static void GetAllFields( Type t, List list ) { GetAllFieldsRecursive( t, true, list ); } public static void GetAllFieldsRecursive( Type t, bool recurse, List list ) { var fieldArr = t.GetFields( BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance ); var en = PredEnumerator.Create( fieldArr.AsEnumerable(), fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null ); list.AddRange( new PredEnumerable( en ) ); if( recurse && t.BaseType != null && t.BaseType != typeof( object ) ) { GetAllFields( t.BaseType, list ); } } public static void GetAllFieldsUntil( Type t, Type tooFar, List list ) { var fieldArr = t.GetFields( BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance ); var en = PredEnumerator.Create( fieldArr.AsEnumerable(), fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null ); list.AddRange( new PredEnumerable( en ) ); if( t.BaseType != null && t.BaseType != tooFar ) { GetAllFields( t.BaseType, list ); } } public static ImmutableList GetAllFields() { return GetAllFields( typeof( T ) ); } public static ImmutableList GetAllFields( Type t ) { { if( s_fieldCache.TryGetValue( t, out var first ) ) return first; } lock( t ) { if( s_fieldCache.TryGetValue( t, out var second ) ) return second; var list = new List(); GetAllFields( t, list ); var immList = list.ToImmutableList(); Interlocked.Exchange( ref s_fieldCache, s_fieldCache.Add( t, immList ) ); return immList; } } public static void GetAllProperties( Type t, List list ) { var propArr = t.GetProperties( BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance ); var en = PredEnumerator.Create( propArr.AsEnumerable(), fa => fa.GetCustomAttribute( typeof( NonSerializedAttribute ) ) == null && !list.Exists( f => f.Name == fa.Name ) ); list.AddRange( new PredEnumerable( en ) ); if( t.BaseType != null && t.BaseType != typeof( object ) ) { GetAllProperties( t.BaseType, list ); } } public static ImmutableList GetAllProperties( Type t ) { if( s_propCache.TryGetValue( t, out var info ) ) return info; var list = new List(); GetAllProperties( t, list ); var immList = list.ToImmutableList(); s_propCache = s_propCache.Add( t, immList ); return immList; } static ImmutableDictionary> s_fieldCache = ImmutableDictionary>.Empty; static ImmutableDictionary> s_propCache = ImmutableDictionary>.Empty; //SLOW static public string TypeToIdentifier( string typename ) { return typename.Replace( '<', '_' ).Replace( '>', '_' ).Replace( ',', '_' ).Replace( ' ', '_' ).Replace( '.', '_' ).Replace( '+', '_' ).Replace( '[', '_' ).Replace( ']', '_' ).Replace( '$', '_' ).Replace( ':', '_' ); } }