#if NET20 || NET30 || !NET_4_6 // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Reflection; using LinqInternal.Collections; using LinqInternal.Core; namespace System.Linq.Expressions.Reimplement { /// /// Represents an expression that applies a delegate or lambda expression to a list of argument expressions. /// [DebuggerTypeProxy(typeof(InvocationExpressionProxy))] public sealed class InvocationExpression : Expression, IArgumentProvider { private IList _arguments; private readonly Expression _lambda; private readonly Type _returnType; internal InvocationExpression(Expression lambda, IList arguments, Type returnType) { _lambda = lambda; _arguments = arguments; _returnType = returnType; } /// /// Gets the static type of the expression that this represents. /// /// The that represents the static type of the expression. public override Type Type { get { return _returnType; } } /// /// Returns the node type of this Expression. Extension nodes should return /// ExpressionType.Extension when overriding this method. /// /// The of the expression. public override ExpressionType NodeType { get { return ExpressionType.Invoke; } } /// /// Gets the delegate or lambda expression to be applied. /// public Expression Expression { get { return _lambda; } } /// /// Gets the arguments that the delegate or lambda expression is applied to. /// public ReadOnlyCollection Arguments { get { return ReturnReadOnly(ref _arguments); } } /// /// Creates a new expression that is like this one, but using the /// supplied children. If all of the children are the same, it will /// return this expression. /// /// The property of the result. /// The property of the result. /// This expression if no children changed, or an expression with the updated children. public InvocationExpression Update(Expression expression, IEnumerable arguments) { if (expression == Expression && arguments == Arguments) { return this; } return Invoke(expression, arguments); } public Expression GetArgument(int index) { return _arguments[index]; } public int ArgumentCount { get { return _arguments.Count; } } protected internal override Expression Accept(ExpressionVisitor visitor) { return visitor.VisitInvocation(this); } internal InvocationExpression Rewrite(Expression lambda, Expression[] arguments) { Debug.Assert(lambda != null); Debug.Assert(arguments == null || arguments.Length == _arguments.Count); return Invoke(lambda, arguments ?? _arguments); } internal LambdaExpression LambdaOperand { get { return (_lambda.NodeType == ExpressionType.Quote) ? (LambdaExpression)((UnaryExpression)_lambda).Operand : (_lambda as LambdaExpression); } } } public partial class Expression { /// ///Creates an that ///applies a delegate or lambda expression to a list of argument expressions. /// /// ///An that ///applies the specified delegate or lambda expression to the provided arguments. /// /// ///An that represents the delegate ///or lambda expression to be applied. /// /// ///An array of objects ///that represent the arguments that the delegate or lambda expression is applied to. /// /// /// is null. /// ///.Type does not represent a delegate type or an .-or-The property of an element of is not assignable to the type of the corresponding parameter of the delegate represented by . /// /// does not contain the same number of elements as the list of parameters for the delegate represented by . public static InvocationExpression Invoke(Expression expression, params Expression[] arguments) { return Invoke(expression, (IEnumerable)arguments); } /// ///Creates an that ///applies a delegate or lambda expression to a list of argument expressions. /// /// ///An that ///applies the specified delegate or lambda expression to the provided arguments. /// /// ///An that represents the delegate ///or lambda expression to be applied. /// /// ///An of objects ///that represent the arguments that the delegate or lambda expression is applied to. /// /// /// is null. /// ///.Type does not represent a delegate type or an .-or-The property of an element of is not assignable to the type of the corresponding parameter of the delegate represented by . /// /// does not contain the same number of elements as the list of parameters for the delegate represented by . public static InvocationExpression Invoke(Expression expression, IEnumerable arguments) { RequiresCanRead(expression, "expression"); var args = arguments.ToReadOnly(); var mi = GetInvokeMethod(expression); ValidateArgumentTypes(mi, ExpressionType.Invoke, ref args); return new InvocationExpression(expression, args, mi.ReturnType); } /// /// Gets the delegate's Invoke method; used by InvocationExpression. /// /// The expression to be invoked. internal static MethodInfo GetInvokeMethod(Expression expression) { var delegateType = expression.Type; if (!expression.Type.IsSubclassOf(typeof(MulticastDelegate))) { var exprType = TypeHelper.FindGenericType(typeof(Expression<>), expression.Type); if (exprType == null) { throw Error.ExpressionTypeNotInvocable(expression.Type); } delegateType = exprType.GetGenericArguments()[0]; } return delegateType.GetMethod("Invoke"); } } } #endif