public static Expression ForEach(ParameterExpression item, Expression source, Expression body) { if (!typeof(IEnumerable).IsAssignableFrom(source.Type)) { throw new InvalidOperationException($"{source.Type} does not implement IEnumerable and cannot be iterated using foreach"); } ParameterExpression enumerator = Expression.Parameter(typeof(IEnumerator), "enumerator"); LabelTarget forEachEnd = Expression.Label(); return(Expression.Block( new[] { item, enumerator }, Expression.Assign( enumerator, Expression.Call(source, EnumerableMembers.GetEnumerator()) ), Expression.Loop( Expression.IfThenElse( Expression.Call(enumerator, EnumerableMembers.MoveNext()), Expression.Block( Expression.Assign(item, Expression.Convert(Expression.Property(enumerator, EnumerableMembers.Current()), item.Type)), body ), Expression.Break(forEachEnd) ), forEachEnd ) )); }
private Expression <Func <IDiff <TType>, IDiff <TType>, IConflictContainer, List <IDiffItem> > > Compile() { ParameterExpression left = Expression.Parameter(typeof(IDiff <TType>), "left"); ParameterExpression right = Expression.Parameter(typeof(IDiff <TType>), "right"); ParameterExpression conflicts = Expression.Parameter(typeof(IConflictContainer), "ret"); ParameterExpression ret = Expression.Parameter(typeof(List <IDiffItem>), "ret"); ParameterExpression leftEnumerator = Expression.Parameter(typeof(IEnumerator <IDiffItem>), "leftEnumerator"); ParameterExpression leftSomeLeft = Expression.Parameter(typeof(bool), "leftSomeLeft"); ParameterExpression rightEnumerator = Expression.Parameter(typeof(IEnumerator <IDiffItem>), "rightEnumerator"); ParameterExpression rightSomeLeft = Expression.Parameter(typeof(bool), "rightSomeLeft"); return(Expression.Lambda <Func <IDiff <TType>, IDiff <TType>, IConflictContainer, List <IDiffItem> > >( Expression.Block( new[] { ret, leftEnumerator, leftSomeLeft, rightEnumerator, rightSomeLeft }, Expression.Assign( ret, Expression.New( ListMembers.NewWithCount(typeof(IDiffItem)), Expression.Add( Expression.Property(left, DiffMembers.Count()), Expression.Property(right, DiffMembers.Count()) ) ) ), Expression.Assign( leftEnumerator, Expression.Call(left, EnumerableMembers.GetEnumerator(typeof(IDiffItem))) ), Expression.Assign( rightEnumerator, Expression.Call(right, EnumerableMembers.GetEnumerator(typeof(IDiffItem))) ), this.MoveEnumerator(leftEnumerator, leftSomeLeft), this.MoveEnumerator(rightEnumerator, rightSomeLeft), Expression.Block(Class <TType> .Properties.Select(x => this.EvaluateProperty(leftEnumerator, leftSomeLeft, rightEnumerator, rightSomeLeft, conflicts, ret, x))), ret ), left, right, conflicts )); }