protected override void CompileInternal() { if (ResultMapFunction != null) { return; } var destVariable = GetDestionationVariable(); ProcessCustomMembers(); ProcessCustomFunctionMembers(); ProcessFlattenedMembers(); ProcessAutoProperties(); CreateQueryableProjection(); var expressions = new List <Expression> { destVariable }; if (BeforeMapHandler != null) { Expression <Action <T, TN> > beforeExpression = (src, dest) => BeforeMapHandler(src, dest); var beforeInvokeExpr = Expression.Invoke(beforeExpression, SourceParameter, destVariable.Left); expressions.Add(beforeInvokeExpr); } expressions.AddRange(PropertyCache.Values); var customProps = CustomPropertyCache.Where(k => !IgnoreMemberList.Contains(k.Key)).Select(k => k.Value); expressions.AddRange(customProps); if (AfterMapHandler != null) { Expression <Action <T, TN> > afterExpression = (src, dest) => AfterMapHandler(src, dest); var afterInvokeExpr = Expression.Invoke(afterExpression, SourceParameter, destVariable.Left); expressions.Add(afterInvokeExpr); } ResultExpressionList.AddRange(expressions); expressions.Add(destVariable.Left); var variables = new List <ParameterExpression>(); var finalExpression = Expression.Block(variables, expressions); var destExpression = destVariable.Left as ParameterExpression; var substituteParameterVisitor = new PreciseSubstituteParameterVisitor( new KeyValuePair <ParameterExpression, ParameterExpression>(SourceParameter, SourceParameter), new KeyValuePair <ParameterExpression, ParameterExpression>(destExpression, destExpression)); var resultExpression = substituteParameterVisitor.Visit(finalExpression) as BlockExpression; var expression = Expression.Lambda <Func <T, TN, TN> >(resultExpression, SourceParameter, DestFakeParameter); ResultMapFunction = expression.Compile(); }
public override BlockExpression MapProperty(Type srcType, Type destType, Expression srcExpression, Expression destExpression) { var sourceVariable = Expression.Variable(srcType, string.Format("{0}_{1}Src", srcType.Name, Guid.NewGuid().ToString().Replace("-", "_"))); var assignSourceFromProp = Expression.Assign(sourceVariable, srcExpression); var mapExpressions = GetMapExpressions(srcType, destType); var mapExprForType = mapExpressions.Item1; var destVariable = Expression.Variable(destType, string.Format("{0}_{1}Dst", destType.Name, Guid.NewGuid().ToString().Replace("-", "_"))); var assignDestFromProp = Expression.Assign(destVariable, destExpression); var ifDestNull = destType.IsPrimitive || destType.IsEnum ? (Expression)StaticExpressions.FalseConstant : Expression.Equal(destExpression, StaticExpressions.NullConstant); var newDestInstanceExp = mapExprForType[0] as BinaryExpression; if (newDestInstanceExp != null) { mapExprForType.RemoveAt(0); var destVar = newDestInstanceExp.Left as ParameterExpression; var assignExistingDestExp = Expression.Assign(destVar, destExpression); var destCondition = Expression.IfThenElse(ifDestNull, newDestInstanceExp, assignExistingDestExp); mapExprForType.Insert(0, destCondition); } var blockForSubstitution = Expression.Block(mapExprForType); var substBlock = new PreciseSubstituteParameterVisitor( new KeyValuePair <ParameterExpression, ParameterExpression>(mapExpressions.Item2, sourceVariable), new KeyValuePair <ParameterExpression, ParameterExpression>(mapExpressions.Item3, destVariable)) .Visit(blockForSubstitution) as BlockExpression; //var substBlock = // new SubstituteParameterVisitor(sourceVariable, destVariable).Visit(blockForSubstitution) as // BlockExpression; var resultMapExprForType = substBlock.Expressions; var assignExp = Expression.Assign(destExpression, destVariable); var expressions = new List <Expression> { assignSourceFromProp, assignDestFromProp }; expressions.AddRange(resultMapExprForType); expressions.Add(assignExp); var parameterExpressions = new List <ParameterExpression> { sourceVariable, destVariable }; var blockExpression = Expression.Block(parameterExpressions, expressions); return(blockExpression); }
protected override void CompileInternal() { if (this.ResultMapFunction != null) { return; } this.ProcessCustomMembers(); this.ProcessCustomFunctionMembers(); this.ProcessFlattenedMembers(); this.ProcessAutoProperties(); var expressions = new List <Expression>(); if (this.BeforeMapHandler != null) { Expression <Action <T, TN> > beforeExpression = (src, dest) => this.BeforeMapHandler(src, dest); var beforeInvokeExpr = Expression.Invoke(beforeExpression, this.SourceParameter, this.DestFakeParameter); expressions.Add(beforeInvokeExpr); } expressions.AddRange(this.PropertyCache.Values); var customProps = this.CustomPropertyCache.Where(k => !this.IgnoreMemberList.Contains(k.Key)).Select(k => k.Value); expressions.AddRange(customProps); if (this.AfterMapHandler != null) { Expression <Action <T, TN> > afterExpression = (src, dest) => this.AfterMapHandler(src, dest); var afterInvokeExpr = Expression.Invoke(afterExpression, this.SourceParameter, this.DestFakeParameter); expressions.Add(afterInvokeExpr); } this.ResultExpressionList.AddRange(expressions); this.ResultExpressionList.Insert(0, this.GetDestionationVariable()); expressions.Add(this.DestFakeParameter); var finalExpression = Expression.Block(expressions); var substituteParameterVisitor = new PreciseSubstituteParameterVisitor( new KeyValuePair <ParameterExpression, ParameterExpression>(this.SourceParameter, this.SourceParameter), new KeyValuePair <ParameterExpression, ParameterExpression>(this.DestFakeParameter, this.DestFakeParameter)); //var substituteParameterVisitor = new SubstituteParameterVisitor(SourceParameter, DestFakeParameter); var resultExpression = substituteParameterVisitor.Visit(finalExpression); var expression = Expression.Lambda <Func <T, TN, TN> >(resultExpression, this.SourceParameter, this.DestFakeParameter); this.ResultMapFunction = expression.Compile(); }
public override BlockExpression MapProperty(Type srcType, Type destType, Expression srcExpression, Expression destExpression, bool newDest) { var sourceVariable = Expression.Variable( srcType, $"{srcType.Name}_{Guid.NewGuid().ToString().Replace("-", "_")}Src"); var assignSourceFromProp = Expression.Assign(sourceVariable, srcExpression); var exprForType = this.GetMapExpressions(srcType, destType); var mapExprForType = exprForType.Item1; var destVariable = Expression.Variable( destType, $"{destType.Name}_{Guid.NewGuid().ToString().Replace("-", "_")}Dst"); var blockForSubstitution = Expression.Block(mapExprForType); var substBlock = new PreciseSubstituteParameterVisitor( new KeyValuePair <ParameterExpression, ParameterExpression>( exprForType.Item2, sourceVariable), new KeyValuePair <ParameterExpression, ParameterExpression>( exprForType.Item3, destVariable)).Visit(blockForSubstitution) as BlockExpression; //var substBlock = // new SubstituteParameterVisitor(sourceVariable, destVariable).Visit(blockForSubstitution) as // BlockExpression; var resultMapExprForType = substBlock.Expressions; var assignExp = Expression.Assign(destExpression, destVariable); var expressions = new List <Expression> { assignSourceFromProp }; expressions.AddRange(resultMapExprForType); expressions.Add(assignExp); var parameterExpressions = new List <ParameterExpression> { sourceVariable, destVariable }; var blockExpression = Expression.Block(parameterExpressions, expressions); return(blockExpression); }
public Expression GetMemberMappingExpression(Expression left, Expression right) { var nullCheckNestedMemberVisitor = new NullCheckNestedMemberVisitor(false); nullCheckNestedMemberVisitor.Visit(right); var destNullableType = Nullable.GetUnderlyingType(left.Type); var sourceNullableType = Nullable.GetUnderlyingType(right.Type); var destType = destNullableType ?? left.Type; var sourceType = sourceNullableType ?? right.Type; if (ComplexMapCondition(sourceType, destType)) { var customMapExpression = GetCustomMapExpression(right.Type, left.Type); if (customMapExpression != null) { var srcExp = Expression.Variable(right.Type, string.Format("{0}Src", Guid.NewGuid().ToString("N"))); var assignSrcExp = Expression.Assign(srcExp, right); var destExp = Expression.Variable(left.Type, string.Format("{0}Dst", Guid.NewGuid().ToString("N"))); var assignDestExp = Expression.Assign(destExp, left); // try precise substitute visitor var substituteParameterVisitor = new PreciseSubstituteParameterVisitor( new KeyValuePair <ParameterExpression, ParameterExpression>( Expression.Variable(right.Type, "srcTyped"), srcExp), new KeyValuePair <ParameterExpression, ParameterExpression>( Expression.Variable(left.Type, "dstTyped"), destExp)); var blockExpression = substituteParameterVisitor.Visit(customMapExpression) as BlockExpression; var assignResultExp = Expression.Assign(left, destExp); var resultBlockExp = Expression.Block(new[] { srcExp, destExp }, assignSrcExp, assignDestExp, blockExpression, assignResultExp); var checkNullExp = Expression.IfThenElse(Expression.Equal(right, Expression.Default(right.Type)), Expression.Assign(left, Expression.Default(left.Type)), resultBlockExp); var releaseExp = Expression.Block(new ParameterExpression[] { }, checkNullExp); return(releaseExp); } var returnTypeDifferenceVisitor = new ReturnTypeDifferenceVisitor(right); returnTypeDifferenceVisitor.Visit(right); // If right is custom member expression / func and return type matches left type // just assign if (left.Type == right.Type && returnTypeDifferenceVisitor.DifferentReturnTypes) { return(Expression.Assign(left, right)); } if (typeof(IConvertible).IsAssignableFrom(destType) && typeof(IConvertible).IsAssignableFrom(sourceType)) { var assignExp = CreateConvertibleAssignExpression(left, right, left.Type, sourceType, destNullableType); return(assignExp); } var mapComplexResult = GetDifferentTypeMemberMappingExpression(right, left); return(nullCheckNestedMemberVisitor.CheckNullExpression != null ? Expression.Condition(nullCheckNestedMemberVisitor.CheckNullExpression, Expression.Assign(left, Expression.Default(left.Type)), mapComplexResult) : mapComplexResult); } var binaryExpression = CreateAssignExpression(left, right, left.Type, destNullableType, sourceNullableType); var conditionalExpression = nullCheckNestedMemberVisitor.CheckNullExpression != null?Expression.Condition(nullCheckNestedMemberVisitor.CheckNullExpression, Expression.Assign(left, Expression.Default(left.Type)), binaryExpression) : (Expression)binaryExpression; return(conditionalExpression); }
protected override void CompileInternal() { if (this.ResultMapFunction != null) { return; } BinaryExpression destVariable = this.GetDestionationVariable(); this.ProcessCustomMembers(); this.ProcessCustomFunctionMembers(); this.ProcessFlattenedMembers(); this.ProcessAutoProperties(); this.CreateQueryableProjection(); List <Expression> expressions = new List <Expression> { destVariable }; if (this.BeforeMapHandler != null) { Expression <Action <T, TN> > beforeExpression = (src, dest) => this.BeforeMapHandler(src, dest); InvocationExpression beforeInvokeExpr = Expression.Invoke(beforeExpression, this.SourceParameter, destVariable.Left); expressions.Add(beforeInvokeExpr); } expressions.AddRange(this.PropertyCache.Values); IEnumerable <Expression> customProps = this.CustomPropertyCache.Where(k => !this.IgnoreMemberList.Contains(k.Key)) .Select(k => k.Value); expressions.AddRange(customProps); if (this.AfterMapHandler != null) { Expression <Action <T, TN> > afterExpression = (src, dest) => this.AfterMapHandler(src, dest); InvocationExpression afterInvokeExpr = Expression.Invoke(afterExpression, this.SourceParameter, destVariable.Left); expressions.Add(afterInvokeExpr); } this.ResultExpressionList.AddRange(expressions); expressions.Add(destVariable.Left); List <ParameterExpression> variables = new List <ParameterExpression>(); BlockExpression finalExpression = Expression.Block(variables, expressions); ParameterExpression destExpression = destVariable.Left as ParameterExpression; PreciseSubstituteParameterVisitor substituteParameterVisitor = new PreciseSubstituteParameterVisitor( new KeyValuePair <ParameterExpression, ParameterExpression>(this.SourceParameter, this.SourceParameter), new KeyValuePair <ParameterExpression, ParameterExpression>(destExpression, destExpression)); BlockExpression resultExpression = substituteParameterVisitor.Visit(finalExpression) as BlockExpression; Expression <Func <T, TN, TN> > expression = Expression.Lambda <Func <T, TN, TN> >( resultExpression, this.SourceParameter, this.DestFakeParameter); this.ResultMapFunction = expression.Compile(); }