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
                           )
                       ));
        }
Beispiel #2
0
        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
                       ));
        }