static CountCache() { var enumerableType = typeof(TEnumerable); var enumerableParameter = Expression.Parameter(enumerableType); var getEnumeratorInfo = enumerableType.GetMethod("GetEnumerator"); var enumeratorType = getEnumeratorInfo.ReturnType; var moveNext = enumeratorType.GetMethod("MoveNext"); if (moveNext is null) { moveNext = typeof(IEnumerator).GetMethod("MoveNext"); } var enumeratorVariable = Expression.Variable(enumeratorType); var counterVariable = Expression.Variable(typeof(long)); var breakLabel = Expression.Label(); var body = Expression.Block(new[] { enumeratorVariable, counterVariable }, Expression.Assign(counterVariable, Expression.Constant(0L)), Expression.Assign(enumeratorVariable, Expression.Call(enumerableParameter, getEnumeratorInfo)), ExpressionEx.Using(enumeratorVariable, ExpressionEx.While( Expression.Equal( Expression.Call(enumeratorVariable, moveNext), Expression.Constant(true)), Expression.Increment(counterVariable))), counterVariable); count = Expression.Lambda <Func <TEnumerable, long> >(body, enumerableParameter).Compile(); }
static Func <TEnumerable, int> CountCustom() { var enumerableParameter = Expression.Parameter(typeof(TEnumerable), "source"); var enumeratorVariable = Expression.Variable(typeof(TEnumerator), "enumerator"); var counterVariable = Expression.Variable(typeof(int), "counter"); var body = Expression.Block(new[] { enumeratorVariable, counterVariable }, Expression.Assign(counterVariable, Expression.Constant(0)), Expression.Assign(enumeratorVariable, Expression.Call(enumerableParameter, "GetEnumerator", null)), ExpressionEx.Using(enumeratorVariable, ExpressionEx.While( Expression.Call(enumeratorVariable, typeof(IEnumerator).GetMethod("MoveNext")), Expression.Assign(counterVariable, Expression.Increment(counterVariable)))), counterVariable); return(Expression.Lambda <Func <TEnumerable, int> >(body, enumerableParameter).Compile()); }
static Func <IEnumerable, int> CreateCount(Type enumerableType) { var enumeratorType = enumerableType .GetMethod("GetEnumerator", BindingFlags.Instance | BindingFlags.Public) .ReturnType; var enumerableParameter = Expression.Parameter(enumerableType, "source"); var enumeratorVariable = Expression.Variable(enumeratorType, "enumerator"); var counterVariable = Expression.Variable(typeof(int), "counter"); var body = Expression.Block(new[] { enumeratorVariable, counterVariable }, Expression.Assign(counterVariable, Expression.Constant(0)), Expression.Assign(enumeratorVariable, Expression.Call(enumerableParameter, "GetEnumerator", null)), ExpressionEx.Using(enumeratorVariable, ExpressionEx.While( Expression.Call(enumeratorVariable, typeof(IEnumerator).GetMethod("MoveNext")), Expression.Assign(counterVariable, Expression.Increment(counterVariable)))), counterVariable); return(Expression.Lambda <Func <IEnumerable, int> >(body, enumerableParameter).Compile()); }