private static void PrepareNestedLambdaTypes(TreeAnalyzer analyzer, Type capturedArgumentType) { var length = analyzer.NestedLambdas.Length; for (var i = 0; i < length; i++) { var lambda = analyzer.NestedLambdas[i]; if (capturedArgumentType != null) { var type = Utils.MapDelegateType(capturedArgumentType .Append(lambda.Key.Parameters.GetTypes()) .Append(lambda.Key.ReturnType)); analyzer.AddStoredItem(lambda.Key, type); } else { analyzer.AddStoredItem(lambda.Key, lambda.Key.Type); } } }
public bool Analyze(Expression expression, params ParameterExpression[] parameters) { switch (expression.NodeType) { case ExpressionType.Parameter: if (parameters.ContainsElement(expression) || this.DefinedVariables.ContainsElement(expression)) { return(true); } this.AddCapturedParameter((ParameterExpression)expression); return(true); case ExpressionType.Lambda: var lambda = (LambdaExpression)expression; var analyzer = new TreeAnalyzer(); if (!analyzer.Analyze(lambda.Body, lambda.Parameters.CastToArray())) { return(false); } this.AddNestedLambda(new KeyValue <LambdaExpression, Expression[]>(lambda, analyzer.DefinedVariables)); var length = analyzer.StoredExpressions.Length; for (var i = 0; i < length; i++) { this.AddStoredItem(analyzer.StoredExpressions[i], analyzer.StoredExpressions[i].Type, analyzer.StoredObjects[i]); } var lambdaLength = analyzer.NestedLambdas.Length; for (var i = 0; i < lambdaLength; i++) { this.AddNestedLambda(analyzer.NestedLambdas[i]); } var capturedLength = analyzer.CapturedParameters.Length; for (var i = 0; i < capturedLength; i++) { this.AddCapturedParameter(analyzer.CapturedParameters[i]); } return(true); case ExpressionType.MemberAccess: return(this.Analyze(((MemberExpression)expression).Expression, parameters)); case ExpressionType.Constant: var constant = (ConstantExpression)expression; if (constant.Value == null || IsInPlaceEmittableConstant(constant.Type, constant.Value)) { return(true); } this.AddStoredItem(constant, constant.Type, constant.Value); return(true); case ExpressionType.New: return(this.Analyze(((NewExpression)expression).Arguments, parameters)); case ExpressionType.MemberInit: var memberInit = (MemberInitExpression)expression; if (!this.Analyze(memberInit.NewExpression, parameters)) { return(false); } return(this.Analyze(memberInit.Bindings, parameters)); case ExpressionType.Block: var block = (BlockExpression)expression; for (var i = 0; i < block.Variables.Count; i++) { this.AddDefinedVariable(block.Variables[i]); } return(this.Analyze(block.Expressions, parameters)); case ExpressionType.Conditional: var condition = (ConditionalExpression)expression; return(this.Analyze(condition.Test, parameters) && this.Analyze(condition.IfTrue, parameters) && this.Analyze(condition.IfFalse, parameters)); case ExpressionType.Default: return(true); case ExpressionType.Call: var call = (MethodCallExpression)expression; return((call.Object == null || this.Analyze(call.Object, parameters)) && this.Analyze(call.Arguments, parameters)); case ExpressionType.Invoke: var invoke = (InvocationExpression)expression; return(this.Analyze(invoke.Expression, parameters) && this.Analyze(invoke.Arguments, parameters)); case ExpressionType.NewArrayInit: return(this.Analyze(((NewArrayExpression)expression).Expressions, parameters)); default: if (expression is UnaryExpression unaryExpression) { return(this.Analyze(unaryExpression.Operand, parameters)); } if (expression is BinaryExpression binaryExpression) { return(this.Analyze(binaryExpression.Left, parameters) && this.Analyze(binaryExpression.Right, parameters)); } break; } return(false); }