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