sharplib/Scr.cs

204 lines
4.4 KiB
C#

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;
}