private static void ConvertReturn(RetValMap retValMap, ExpressionBlockBuilder block, Expression invoke, ParameterExpression retVal) { if (retValMap.Method == typeof(void)) { if (retValMap.Delegate != typeof(void)) { // add default(_delegateReturn) block.Add(Expression.Default(retValMap.Delegate)); } else if (block.Last != invoke) { // should we return void? block.Add(_void); } return; } if (retValMap.Delegate == typeof(void)) { block.Add(_void); return; } // try optimize local variable Expression result; if (block.Last is BinaryExpression binary && binary.NodeType == ExpressionType.Assign && binary.Left == retVal) { result = binary.Right; block.RemoveVariable(retVal); block.RemoveLast(); }
private static ParameterExpression PrepareInvoke(RetValMap retValMap, ExpressionBlockBuilder block, Expression invoke) { if (retValMap.Method == typeof(void) || retValMap.Delegate == typeof(void)) { // no local variables for void block.Add(invoke); return(null); } var variable = Expression.Variable(retValMap.Method); var assign = Expression.Assign(variable, invoke); block.AddVariable(variable); block.Add(assign); return(variable); }
private static Expression Prepare(ArgMap map, ExpressionBlockBuilder block, ParameterExpression p) { if (!map.Method.IsOut && !map.Method.IsByRef) { // normal parameter return(map.Method.Type == map.Delegate.Type ? (Expression)p : Expression.Convert(p, map.Method.Type)); } // out or ref var mt = map.Method.Type.RemoveByRef(); var dt = map.Delegate.Type.RemoveByRef(); if (mt == dt) { return(p); } var localVariable = Expression.Variable(mt); block.AddVariable(localVariable); if (map.Method.IsOut) { return(localVariable); } // ref var value = map.Delegate.IsOut ? (Expression)Expression.Default(mt) : Expression.Convert(p, mt); var assign = Expression.Assign(localVariable, value); block.Add(assign); return(localVariable); }
private BlockExpression BuildExpressionBlock(Type targetType, ParameterExpression targetInstanceParameter, ParameterExpression dataReaderParameter, PropertyInfo indexerProperty) { var expressionBlockBuilder = new ExpressionBlockBuilder(targetInstanceParameter.Type, new[] { targetInstanceParameter }); return(expressionBlockBuilder .Add(Expression.Assign(targetInstanceParameter, Expression.New(targetType))) .AddRange(BuildPrimitivePropertyExpressions(targetType, targetInstanceParameter, dataReaderParameter, indexerProperty)) .AddRange(BuildComplexPropertyExpressions(targetType, targetInstanceParameter, dataReaderParameter, indexerProperty)) .Add(targetInstanceParameter) .Build()); }
private static void Finish(ArgMap map, ExpressionBlockBuilder block, Expression prepare, ParameterExpression p) { // Not out and (Not By Ref or ([byRef] and not (delegate ref or delegate out) if (!map.Method.IsOut && (!map.Method.IsByRef || !(map.Delegate.IsByRef || map.Delegate.IsOut))) { return; } // out/ref and typeSame - do nothing var mt = map.Method.Type.RemoveByRef(); var dt = map.Delegate.Type.RemoveByRef(); if (mt == dt) { return; } // convert and assign back var convertResult = Expression.Convert(prepare, dt); var assign = Expression.Assign(p, convertResult); block.Add(assign); }