示例#1
0
        private BlockExpression MapCollectionCountEquals(Type tCol, Type tnCol, Expression sourceVariable,
                                                         Expression destVariable)
        {
            var sourceType = GetCollectionElementType(tCol);
            var destType   = GetCollectionElementType(tnCol);

            // Source enumeration
            var closedEnumeratorSourceType = typeof(IEnumerator <>).MakeGenericType(sourceType);
            var closedEnumerableSourceType = GenericEnumerableType.MakeGenericType(sourceType);
            var enumeratorSrc   = Expression.Variable(closedEnumeratorSourceType, string.Format("{0}EnumSrc", Guid.NewGuid().ToString("N")));
            var assignToEnumSrc = Expression.Assign(enumeratorSrc,
                                                    Expression.Call(sourceVariable, closedEnumerableSourceType.GetMethod("GetEnumerator")));
            var doMoveNextSrc           = Expression.Call(enumeratorSrc, typeof(IEnumerator).GetMethod("MoveNext"));
            var currentSrc              = Expression.Property(enumeratorSrc, "Current");
            var srcItmVarExp            = Expression.Variable(sourceType, string.Format("{0}ItmSrc", Guid.NewGuid().ToString("N")));
            var assignSourceItmFromProp = Expression.Assign(srcItmVarExp, currentSrc);

            // dest enumeration
            var closedEnumeratorDestType = typeof(IEnumerator <>).MakeGenericType(destType);
            var closedEnumerableDestType = GenericEnumerableType.MakeGenericType(destType);
            var enumeratorDest           = Expression.Variable(closedEnumeratorDestType, string.Format("{0}EnumDst", Guid.NewGuid().ToString("N")));
            var assignToEnumDest         = Expression.Assign(enumeratorDest,
                                                             Expression.Call(destVariable, closedEnumerableDestType.GetMethod("GetEnumerator")));
            var doMoveNextDest        = Expression.Call(enumeratorDest, typeof(IEnumerator).GetMethod("MoveNext"));
            var currentDest           = Expression.Property(enumeratorDest, "Current");
            var destItmVarExp         = Expression.Variable(destType, string.Format("{0}ItmDst", Guid.NewGuid().ToString("N")));
            var assignDestItmFromProp = Expression.Assign(destItmVarExp, currentDest);

            var mapExprForType = GetMemberMappingExpression(destItmVarExp, srcItmVarExp, false);

            var ifTrueBlock = Expression.Block(new[] { srcItmVarExp, destItmVarExp },
                                               new[] { assignSourceItmFromProp, assignDestItmFromProp, mapExprForType });

            var brk            = Expression.Label();
            var loopExpression = Expression.Loop(
                Expression.IfThenElse(
                    Expression.AndAlso(Expression.NotEqual(doMoveNextSrc, StaticExpressions.FalseConstant),
                                       Expression.NotEqual(doMoveNextDest, StaticExpressions.FalseConstant)),
                    ifTrueBlock
                    , Expression.Break(brk))
                , brk);

            var parameters = new List <ParameterExpression> {
                enumeratorSrc, enumeratorDest
            };
            var expressions = new List <Expression>
            {
                assignToEnumSrc,
                assignToEnumDest,
                loopExpression
            };

            var blockExpression = Expression.Block(parameters, expressions);

            return(blockExpression);
        }
示例#2
0
        private BlockExpression MapCollectionSourcePrevail(Expression destVariable, Type sourceType,
                                                           Expression sourceVariable, Type destType)
        {
            // Source enumeration
            var closedEnumeratorSourceType = typeof(IEnumerator <>).MakeGenericType(sourceType);
            var closedEnumerableSourceType = GenericEnumerableType.MakeGenericType(sourceType);
            var enumeratorSrc   = Expression.Variable(closedEnumeratorSourceType, string.Format("{0}EnumSrc", Guid.NewGuid().ToString("N")));
            var assignToEnumSrc = Expression.Assign(enumeratorSrc,
                                                    Expression.Call(sourceVariable, closedEnumerableSourceType.GetMethod("GetEnumerator")));
            var doMoveNextSrc = Expression.Call(enumeratorSrc, typeof(IEnumerator).GetMethod("MoveNext"));
            var currentSrc    = Expression.Property(enumeratorSrc, "Current");

            var srcItmVarExp            = Expression.Variable(sourceType, string.Format("{0}ItmSrc", Guid.NewGuid().ToString("N")));
            var assignSourceItmFromProp = Expression.Assign(srcItmVarExp, currentSrc);

            // dest enumeration
            var closedEnumeratorDestType = typeof(IEnumerator <>).MakeGenericType(destType);
            var closedEnumerableDestType = GenericEnumerableType.MakeGenericType(destType);
            var enumeratorDest           = Expression.Variable(closedEnumeratorDestType, string.Format("{0}EnumDst", Guid.NewGuid().ToString("N")));
            var assignToEnumDest         = Expression.Assign(enumeratorDest,
                                                             Expression.Call(destVariable, closedEnumerableDestType.GetMethod("GetEnumerator")));
            var doMoveNextDest = Expression.Call(enumeratorDest, typeof(IEnumerator).GetMethod("MoveNext"));

            var currentDest           = Expression.Property(enumeratorDest, "Current");
            var destItmVarExp         = Expression.Variable(destType, string.Format("{0}ItmDst", Guid.NewGuid().ToString("N")));
            var assignDestItmFromProp = Expression.Assign(destItmVarExp, currentDest);

            var ifTrueBlock = IfElseExpr(srcItmVarExp, destItmVarExp, assignDestItmFromProp);

            // If destination list is empty
            var mapExprForType = GetMemberMappingExpression(destItmVarExp, srcItmVarExp, true);

            var destCollection = typeof(ICollection <>).MakeGenericType(destType);

            var addToNewCollNew = Expression.Call(destVariable, destCollection.GetMethod("Add"), destItmVarExp);

            var ifFalseBlock = Expression.Block(new ParameterExpression[] {}, new[] { mapExprForType, addToNewCollNew });

            var endOfListExp           = Expression.Variable(typeof(bool), "endOfList");
            var assignInitEndOfListExp = Expression.Assign(endOfListExp, StaticExpressions.FalseConstant);

            var ifNotEndOfListExp = Expression.IfThen(Expression.Equal(endOfListExp, StaticExpressions.FalseConstant),
                                                      Expression.Assign(endOfListExp, Expression.Not(doMoveNextDest)));

            var mapAndAddItemExp = Expression.IfThenElse(endOfListExp, ifFalseBlock, ifTrueBlock);

            var innerLoopBlock = Expression.Block(new[] { srcItmVarExp, destItmVarExp },
                                                  new Expression[] { assignSourceItmFromProp, ifNotEndOfListExp, mapAndAddItemExp });

            var loopExpression = CreateLoopExpression(doMoveNextSrc, innerLoopBlock);

            var blockExpression = Expression.Block(new[] { endOfListExp, enumeratorSrc, enumeratorDest },
                                                   new Expression[] { assignInitEndOfListExp, assignToEnumSrc, assignToEnumDest, loopExpression });

            return(blockExpression);
        }
示例#3
0
        private BlockExpression MapCollectionNotCountEquals(Type tCol, Type tnCol, Expression sourceVariable,
                                                            Expression destVariable)
        {
            var sourceType = GetCollectionElementType(tCol);
            var destType   = GetCollectionElementType(tnCol);

            var destList       = typeof(List <>).MakeGenericType(destType);
            var destCollection = typeof(ICollection <>).MakeGenericType(destType);

            BlockExpression resultExpression;
            var             isICollection = !destVariable.Type.IsArray && (destVariable.Type.GetInterfaces()
                                                                           .FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ICollection <>)) != null ||
                                                                           destVariable.Type == destCollection);

            var srcCount  = Expression.Call(typeof(Enumerable), "Count", new[] { sourceType }, sourceVariable);
            var destCount = Expression.Call(typeof(Enumerable), "Count", new[] { destType }, destVariable);

            if (isICollection)
            {
                // If it is a list and destCount greater than srcCount

                var equalsBlockExp = MapCollectionCountEquals(tCol, tnCol, sourceVariable, destVariable);

                var getFirstEnumExp    = Expression.Call(typeof(Enumerable), "First", new[] { destType }, destVariable);
                var removeCollFirstExp = Expression.Call(destVariable, destCollection.GetMethod("Remove"),
                                                         getFirstEnumExp);

                var brkColRem             = Expression.Label();
                var loopToDropColElements = Expression.Loop(
                    Expression.IfThenElse(Expression.GreaterThan(destCount, srcCount),
                                          removeCollFirstExp
                                          , Expression.Break(brkColRem))
                    , brkColRem);

                var collRemoveExps = new List <Expression> {
                    loopToDropColElements, equalsBlockExp
                };
                var collRemoveBlockExp = Expression.Block(collRemoveExps);

                // List and Collection - if src count greater than dest

                var mapCollectionSourcePrevail = MapCollectionSourcePrevail(destVariable, sourceType, sourceVariable,
                                                                            destType);
                var collBlock = Expression.IfThenElse(Expression.GreaterThan(destCount, srcCount), collRemoveBlockExp,
                                                      mapCollectionSourcePrevail);
                resultExpression = Expression.Block(new ParameterExpression[] {}, new Expression[] { collBlock });
            }
            else
            {
                // Else

                var destListType    = typeof(List <>).MakeGenericType(destType);
                var destVarExp      = Expression.Variable(destListType, string.Format("{0}InterimDst", Guid.NewGuid().ToString("N")));
                var constructorInfo = destListType.GetConstructor(new Type[] { typeof(int) });

                var newColl    = Expression.New(constructorInfo, srcCount);
                var destAssign = Expression.Assign(destVarExp, newColl);

                // Source enumeration
                var closedEnumeratorSourceType = typeof(IEnumerator <>).MakeGenericType(sourceType);
                var closedEnumerableSourceType = GenericEnumerableType.MakeGenericType(sourceType);
                var enumeratorSrc   = Expression.Variable(closedEnumeratorSourceType, string.Format("{0}EnumSrc", Guid.NewGuid().ToString("N")));
                var assignToEnumSrc = Expression.Assign(enumeratorSrc,
                                                        Expression.Call(sourceVariable, closedEnumerableSourceType.GetMethod("GetEnumerator")));
                var doMoveNextSrc = Expression.Call(enumeratorSrc, typeof(IEnumerator).GetMethod("MoveNext"));
                var currentSrc    = Expression.Property(enumeratorSrc, "Current");

                var srcItmVarExp            = Expression.Variable(sourceType, string.Format("{0}ItmSrc", Guid.NewGuid().ToString("N")));
                var assignSourceItmFromProp = Expression.Assign(srcItmVarExp, currentSrc);

                // dest enumeration
                var closedEnumeratorDestType = typeof(IEnumerator <>).MakeGenericType(destType);
                var closedEnumerableDestType = GenericEnumerableType.MakeGenericType(destType);
                var enumeratorDest           = Expression.Variable(closedEnumeratorDestType, string.Format("{0}EnumDst", Guid.NewGuid().ToString("N")));
                var assignToEnumDest         = Expression.Assign(enumeratorDest,
                                                                 Expression.Call(destVariable, closedEnumerableDestType.GetMethod("GetEnumerator")));
                var doMoveNextDest = Expression.Call(enumeratorDest, typeof(IEnumerator).GetMethod("MoveNext"));

                var currentDest           = Expression.Property(enumeratorDest, "Current");
                var destItmVarExp         = Expression.Variable(destType, string.Format("{0}ItmDst", Guid.NewGuid().ToString("N")));
                var assignDestItmFromProp = Expression.Assign(destItmVarExp, currentDest);


                // If destination list is empty
                var mapExprForType = GetMemberMappingExpression(destItmVarExp, srcItmVarExp, true);

                var ifTrueBlock = IfElseExpr(srcItmVarExp, destItmVarExp, assignDestItmFromProp);

                var mapAndAddItemExp = Expression.IfThenElse(doMoveNextDest, ifTrueBlock, mapExprForType);
                var addToNewCollNew  = Expression.Call(destVarExp, "Add", null, destItmVarExp);

                var innerLoopBlock = Expression.Block(new[] { srcItmVarExp, destItmVarExp },
                                                      new Expression[] { assignSourceItmFromProp, mapAndAddItemExp, addToNewCollNew });

                var loopExpression = CreateLoopExpression(doMoveNextSrc, innerLoopBlock);

                var resultCollection = ConvertCollection(destVariable.Type, destList, destType, destVarExp);

                var assignResult = Expression.Assign(destVariable, resultCollection);

                var parameters = new List <ParameterExpression> {
                    destVarExp, enumeratorSrc, enumeratorDest
                };
                var expressions = new List <Expression>
                {
                    destAssign,
                    assignToEnumSrc,
                    assignToEnumDest,
                    loopExpression,
                    assignResult
                };

                resultExpression = Expression.Block(parameters, expressions);
            }

            return(resultExpression);
        }