1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Microsoft Public License. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Microsoft Public License, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Microsoft Public License.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Collections.Generic;
18 using System.Collections.ObjectModel;
19 using System.Diagnostics;
20 using System.Dynamic.Utils;
21 using System.Reflection;
22 using System.Runtime.CompilerServices;
29 namespace Microsoft.Scripting.Ast {
31 namespace System.Linq.Expressions {
34 /// Represents a call to either static or an instance method.
37 [DebuggerTypeProxy(typeof(Expression.MethodCallExpressionProxy))]
39 public class MethodCallExpression : Expression, IArgumentProvider {
40 private readonly MethodInfo _method;
42 internal MethodCallExpression(MethodInfo method) {
47 internal virtual Expression GetInstance() {
52 /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
54 /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
55 public sealed override ExpressionType NodeType {
56 get { return ExpressionType.Call; }
60 /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
62 /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
63 public sealed override Type Type {
64 get { return _method.ReturnType; }
68 /// Gets the <see cref="MethodInfo" /> for the method to be called.
70 public MethodInfo Method {
71 get { return _method; }
75 /// Gets the <see cref="Expression" /> that represents the instance
76 /// for instance method calls or null for static method cals.
78 public Expression Object {
79 get { return GetInstance(); }
83 /// Gets a collection of expressions that represent arguments to the method call.
85 public ReadOnlyCollection<Expression> Arguments {
86 get { return GetOrMakeArguments(); }
90 /// Creates a new expression that is like this one, but using the
91 /// supplied children. If all of the children are the same, it will
92 /// return this expression.
94 /// <param name="object">The <see cref="Object" /> property of the result.</param>
95 /// <param name="arguments">The <see cref="Arguments" /> property of the result.</param>
96 /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
97 public MethodCallExpression Update(Expression @object, IEnumerable<Expression> arguments) {
98 if (@object == Object && arguments == Arguments) {
101 return Expression.Call(@object, Method, arguments);
104 internal virtual ReadOnlyCollection<Expression> GetOrMakeArguments() {
105 throw ContractUtils.Unreachable;
109 /// Dispatches to the specific visit method for this node type.
111 protected internal override Expression Accept(ExpressionVisitor visitor) {
112 return visitor.VisitMethodCall(this);
116 /// Returns a new MethodCallExpression replacing the existing instance/args with the
117 /// newly provided instance and args. Arguments can be null to use the existing
120 /// This helper is provided to allow re-writing of nodes to not depend on the specific optimized
121 /// subclass of MethodCallExpression which is being used.
123 internal virtual MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
124 throw ContractUtils.Unreachable;
127 #region IArgumentProvider Members
129 Expression IArgumentProvider.GetArgument(int index) {
130 throw ContractUtils.Unreachable;
133 int IArgumentProvider.ArgumentCount {
134 get { throw ContractUtils.Unreachable; }
140 #region Specialized Subclasses
142 internal class MethodCallExpressionN : MethodCallExpression, IArgumentProvider {
143 private IList<Expression> _arguments;
145 public MethodCallExpressionN(MethodInfo method, IList<Expression> args)
150 Expression IArgumentProvider.GetArgument(int index) {
151 return _arguments[index];
154 int IArgumentProvider.ArgumentCount {
156 return _arguments.Count;
160 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
161 return ReturnReadOnly(ref _arguments);
164 internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
165 Debug.Assert(instance == null);
166 Debug.Assert(args == null || args.Count == _arguments.Count);
168 return Expression.Call(Method, args ?? _arguments);
172 internal class InstanceMethodCallExpressionN : MethodCallExpression, IArgumentProvider {
173 private IList<Expression> _arguments;
174 private readonly Expression _instance;
176 public InstanceMethodCallExpressionN(MethodInfo method, Expression instance, IList<Expression> args)
178 _instance = instance;
182 Expression IArgumentProvider.GetArgument(int index) {
183 return _arguments[index];
186 int IArgumentProvider.ArgumentCount {
188 return _arguments.Count;
192 internal override Expression GetInstance() {
196 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
197 return ReturnReadOnly(ref _arguments);
200 internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
201 Debug.Assert(instance != null);
202 Debug.Assert(args == null || args.Count == _arguments.Count);
204 return Expression.Call(instance, Method, args ?? _arguments);
208 internal class MethodCallExpression1 : MethodCallExpression, IArgumentProvider {
209 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
211 public MethodCallExpression1(MethodInfo method, Expression arg0)
216 Expression IArgumentProvider.GetArgument(int index) {
218 case 0: return ReturnObject<Expression>(_arg0);
219 default: throw new InvalidOperationException();
223 int IArgumentProvider.ArgumentCount {
229 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
230 return ReturnReadOnly(this, ref _arg0);
233 internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
234 Debug.Assert(instance == null);
235 Debug.Assert(args == null || args.Count == 1);
238 return Expression.Call(Method, args[0]);
241 return Expression.Call(Method, ReturnObject<Expression>(_arg0));
245 internal class MethodCallExpression2 : MethodCallExpression, IArgumentProvider {
246 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
247 private readonly Expression _arg1; // storage for the 2nd arg
249 public MethodCallExpression2(MethodInfo method, Expression arg0, Expression arg1)
255 Expression IArgumentProvider.GetArgument(int index) {
257 case 0: return ReturnObject<Expression>(_arg0);
258 case 1: return _arg1;
259 default: throw new InvalidOperationException();
263 int IArgumentProvider.ArgumentCount {
269 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
270 return ReturnReadOnly(this, ref _arg0);
273 internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
274 Debug.Assert(instance == null);
275 Debug.Assert(args == null || args.Count == 2);
278 return Expression.Call(Method, args[0], args[1]);
280 return Expression.Call(Method, ReturnObject<Expression>(_arg0), _arg1);
284 internal class MethodCallExpression3 : MethodCallExpression, IArgumentProvider {
285 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
286 private readonly Expression _arg1, _arg2; // storage for the 2nd - 3rd args.
288 public MethodCallExpression3(MethodInfo method, Expression arg0, Expression arg1, Expression arg2)
295 Expression IArgumentProvider.GetArgument(int index) {
297 case 0: return ReturnObject<Expression>(_arg0);
298 case 1: return _arg1;
299 case 2: return _arg2;
300 default: throw new InvalidOperationException();
304 int IArgumentProvider.ArgumentCount {
310 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
311 return ReturnReadOnly(this, ref _arg0);
314 internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
315 Debug.Assert(instance == null);
316 Debug.Assert(args == null || args.Count == 3);
319 return Expression.Call(Method, args[0], args[1], args[2]);
321 return Expression.Call(Method, ReturnObject<Expression>(_arg0), _arg1, _arg2);
325 internal class MethodCallExpression4 : MethodCallExpression, IArgumentProvider {
326 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
327 private readonly Expression _arg1, _arg2, _arg3; // storage for the 2nd - 4th args.
329 public MethodCallExpression4(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
337 Expression IArgumentProvider.GetArgument(int index) {
339 case 0: return ReturnObject<Expression>(_arg0);
340 case 1: return _arg1;
341 case 2: return _arg2;
342 case 3: return _arg3;
343 default: throw new InvalidOperationException();
347 int IArgumentProvider.ArgumentCount {
353 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
354 return ReturnReadOnly(this, ref _arg0);
357 internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
358 Debug.Assert(instance == null);
359 Debug.Assert(args == null || args.Count == 4);
362 return Expression.Call(Method, args[0], args[1], args[2], args[3]);
364 return Expression.Call(Method, ReturnObject<Expression>(_arg0), _arg1, _arg2, _arg3);
368 internal class MethodCallExpression5 : MethodCallExpression, IArgumentProvider {
369 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
370 private readonly Expression _arg1, _arg2, _arg3, _arg4; // storage for the 2nd - 5th args.
372 public MethodCallExpression5(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4)
381 Expression IArgumentProvider.GetArgument(int index) {
383 case 0: return ReturnObject<Expression>(_arg0);
384 case 1: return _arg1;
385 case 2: return _arg2;
386 case 3: return _arg3;
387 case 4: return _arg4;
388 default: throw new InvalidOperationException();
392 int IArgumentProvider.ArgumentCount {
398 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
399 return ReturnReadOnly(this, ref _arg0);
402 internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
403 Debug.Assert(instance == null);
404 Debug.Assert(args == null || args.Count == 5);
407 return Expression.Call(Method, args[0], args[1], args[2], args[3], args[4]);
410 return Expression.Call(Method, ReturnObject<Expression>(_arg0), _arg1, _arg2, _arg3, _arg4);
414 internal class InstanceMethodCallExpression2 : MethodCallExpression, IArgumentProvider {
415 private readonly Expression _instance;
416 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
417 private readonly Expression _arg1; // storage for the 2nd argument
419 public InstanceMethodCallExpression2(MethodInfo method, Expression instance, Expression arg0, Expression arg1)
421 Debug.Assert(instance != null);
423 _instance = instance;
428 Expression IArgumentProvider.GetArgument(int index) {
430 case 0: return ReturnObject<Expression>(_arg0);
431 case 1: return _arg1;
432 default: throw new InvalidOperationException();
436 int IArgumentProvider.ArgumentCount {
442 internal override Expression GetInstance() {
446 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
447 return ReturnReadOnly(this, ref _arg0);
450 internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
451 Debug.Assert(instance != null);
452 Debug.Assert(args == null || args.Count == 2);
455 return Expression.Call(instance, Method, args[0], args[1]);
457 return Expression.Call(instance, Method, ReturnObject<Expression>(_arg0), _arg1);
461 internal class InstanceMethodCallExpression3 : MethodCallExpression, IArgumentProvider {
462 private readonly Expression _instance;
463 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
464 private readonly Expression _arg1, _arg2; // storage for the 2nd - 3rd argument
466 public InstanceMethodCallExpression3(MethodInfo method, Expression instance, Expression arg0, Expression arg1, Expression arg2)
468 Debug.Assert(instance != null);
470 _instance = instance;
476 Expression IArgumentProvider.GetArgument(int index) {
478 case 0: return ReturnObject<Expression>(_arg0);
479 case 1: return _arg1;
480 case 2: return _arg2;
481 default: throw new InvalidOperationException();
485 int IArgumentProvider.ArgumentCount {
491 internal override Expression GetInstance() {
495 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
496 return ReturnReadOnly(this, ref _arg0);
499 internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
500 Debug.Assert(instance != null);
501 Debug.Assert(args == null || args.Count == 3);
504 return Expression.Call(instance, Method, args[0], args[1], args[2]);
506 return Expression.Call(instance, Method, ReturnObject<Expression>(_arg0), _arg1, _arg2);
512 public partial class Expression {
516 ///<summary>Creates a <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that represents a call to a static method that takes one argument.</summary>
517 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
518 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
519 ///<param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
520 ///<exception cref="T:System.ArgumentNullException">
521 ///<paramref name="method" /> is null.</exception>
522 public static MethodCallExpression Call(MethodInfo method, Expression arg0) {
523 ContractUtils.RequiresNotNull(method, "method");
524 ContractUtils.RequiresNotNull(arg0, "arg0");
526 ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method);
528 ValidateArgumentCount(method, ExpressionType.Call, 1, pis);
530 arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
532 return new MethodCallExpression1(method, arg0);
535 ///<summary>Creates a <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that represents a call to a static method that takes two arguments.</summary>
536 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
537 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
538 ///<param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
539 ///<param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
540 ///<exception cref="T:System.ArgumentNullException">
541 ///<paramref name="method" /> is null.</exception>
542 public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1) {
543 ContractUtils.RequiresNotNull(method, "method");
544 ContractUtils.RequiresNotNull(arg0, "arg0");
545 ContractUtils.RequiresNotNull(arg1, "arg1");
547 ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method);
549 ValidateArgumentCount(method, ExpressionType.Call, 2, pis);
551 arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
552 arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
554 return new MethodCallExpression2(method, arg0, arg1);
557 ///<summary>Creates a <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that represents a call to a static method that takes three arguments.</summary>
558 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
559 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
560 ///<param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
561 ///<param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
562 ///<param name="arg2">The <see cref="Expression" /> that represents the third argument.</param>
563 ///<exception cref="T:System.ArgumentNullException">
564 ///<paramref name="method" /> is null.</exception>
565 public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1, Expression arg2) {
566 ContractUtils.RequiresNotNull(method, "method");
567 ContractUtils.RequiresNotNull(arg0, "arg0");
568 ContractUtils.RequiresNotNull(arg1, "arg1");
569 ContractUtils.RequiresNotNull(arg2, "arg2");
571 ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method);
573 ValidateArgumentCount(method, ExpressionType.Call, 3, pis);
575 arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
576 arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
577 arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]);
579 return new MethodCallExpression3(method, arg0, arg1, arg2);
582 ///<summary>Creates a <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that represents a call to a static method that takes four arguments.</summary>
583 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
584 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
585 ///<param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
586 ///<param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
587 ///<param name="arg2">The <see cref="Expression" /> that represents the third argument.</param>
588 ///<param name="arg3">The <see cref="Expression" /> that represents the fourth argument.</param>
589 ///<exception cref="T:System.ArgumentNullException">
590 ///<paramref name="method" /> is null.</exception>
591 public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
592 ContractUtils.RequiresNotNull(method, "method");
593 ContractUtils.RequiresNotNull(arg0, "arg0");
594 ContractUtils.RequiresNotNull(arg1, "arg1");
595 ContractUtils.RequiresNotNull(arg2, "arg2");
596 ContractUtils.RequiresNotNull(arg3, "arg3");
598 ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method);
600 ValidateArgumentCount(method, ExpressionType.Call, 4, pis);
602 arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
603 arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
604 arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]);
605 arg3 = ValidateOneArgument(method, ExpressionType.Call, arg3, pis[3]);
607 return new MethodCallExpression4(method, arg0, arg1, arg2, arg3);
610 ///<summary>Creates a <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that represents a call to a static method that takes five arguments.</summary>
611 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
612 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
613 ///<param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
614 ///<param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
615 ///<param name="arg2">The <see cref="Expression" /> that represents the third argument.</param>
616 ///<param name="arg3">The <see cref="Expression" /> that represents the fourth argument.</param>
617 ///<param name="arg4">The <see cref="Expression" /> that represents the fifth argument.</param>
618 ///<exception cref="T:System.ArgumentNullException">
619 ///<paramref name="method" /> is null.</exception>
620 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
621 public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4) {
622 ContractUtils.RequiresNotNull(method, "method");
623 ContractUtils.RequiresNotNull(arg0, "arg0");
624 ContractUtils.RequiresNotNull(arg1, "arg1");
625 ContractUtils.RequiresNotNull(arg2, "arg2");
626 ContractUtils.RequiresNotNull(arg3, "arg3");
627 ContractUtils.RequiresNotNull(arg4, "arg4");
629 ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method);
631 ValidateArgumentCount(method, ExpressionType.Call, 5, pis);
633 arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
634 arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
635 arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]);
636 arg3 = ValidateOneArgument(method, ExpressionType.Call, arg3, pis[3]);
637 arg4 = ValidateOneArgument(method, ExpressionType.Call, arg4, pis[4]);
639 return new MethodCallExpression5(method, arg0, arg1, arg2, arg3, arg4);
643 /// Creates a <see cref="MethodCallExpression" /> that represents a call to a static (Shared in Visual Basic) method.
645 /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
646 /// <param name="arguments">The array of one or more of <see cref="Expression" /> that represents the call arguments.</param>
647 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
648 public static MethodCallExpression Call(MethodInfo method, params Expression[] arguments) {
649 return Call(null, method, arguments);
653 /// Creates a <see cref="MethodCallExpression" /> that represents a call to a static (Shared in Visual Basic) method.
655 /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
656 /// <param name="arguments">A collection of <see cref="Expression" /> that represents the call arguments.</param>
657 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
658 public static MethodCallExpression Call(MethodInfo method, IEnumerable<Expression> arguments) {
659 return Call(null, method, arguments);
663 /// Creates a <see cref="MethodCallExpression" /> that represents a call to a method that takes no arguments.
665 /// <param name="instance">An <see cref="Expression" /> that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method).</param>
666 /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
667 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
668 public static MethodCallExpression Call(Expression instance, MethodInfo method) {
669 return Call(instance, method, EmptyReadOnlyCollection<Expression>.Instance);
673 /// Creates a <see cref="MethodCallExpression" /> that represents a method call.
675 /// <param name="instance">An <see cref="Expression" /> that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method).</param>
676 /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
677 /// <param name="arguments">An array of one or more of <see cref="Expression" /> that represents the call arguments.</param>
678 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
679 public static MethodCallExpression Call(Expression instance, MethodInfo method, params Expression[] arguments) {
680 return Call(instance, method, (IEnumerable<Expression>)arguments);
684 /// Creates a <see cref="MethodCallExpression" /> that represents a call to a method that takes two arguments.
686 /// <param name="instance">An <see cref="Expression" /> that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method).</param>
687 /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
688 /// <param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
689 /// <param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
690 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
691 public static MethodCallExpression Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1) {
692 ContractUtils.RequiresNotNull(method, "method");
693 ContractUtils.RequiresNotNull(arg0, "arg0");
694 ContractUtils.RequiresNotNull(arg1, "arg1");
696 ParameterInfo[] pis = ValidateMethodAndGetParameters(instance, method);
698 ValidateArgumentCount(method, ExpressionType.Call, 2, pis);
700 arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
701 arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
703 if (instance != null) {
704 return new InstanceMethodCallExpression2(method, instance, arg0, arg1);
707 return new MethodCallExpression2(method, arg0, arg1);
711 /// Creates a <see cref="MethodCallExpression" /> that represents a call to a method that takes three arguments.
713 /// <param name="instance">An <see cref="Expression" /> that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method).</param>
714 /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
715 /// <param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
716 /// <param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
717 /// <param name="arg2">The <see cref="Expression" /> that represents the third argument.</param>
718 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
719 public static MethodCallExpression Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1, Expression arg2) {
720 ContractUtils.RequiresNotNull(method, "method");
721 ContractUtils.RequiresNotNull(arg0, "arg0");
722 ContractUtils.RequiresNotNull(arg1, "arg1");
723 ContractUtils.RequiresNotNull(arg2, "arg2");
725 ParameterInfo[] pis = ValidateMethodAndGetParameters(instance, method);
727 ValidateArgumentCount(method, ExpressionType.Call, 3, pis);
729 arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
730 arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
731 arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]);
733 if (instance != null) {
734 return new InstanceMethodCallExpression3(method, instance, arg0, arg1, arg2);
736 return new MethodCallExpression3(method, arg0, arg1, arg2);
739 ///<summary>Creates a <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that represents a call to an instance method by calling the appropriate factory method.</summary>
740 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" />, the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> property equal to <paramref name="instance" />, <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> set to the <see cref="T:System.Reflection.MethodInfo" /> that represents the specified instance method, and <see cref="P:System.Linq.Expressions.MethodCallExpression.Arguments" /> set to the specified arguments.</returns>
741 ///<param name="instance">An <see cref="T:System.Linq.Expressions.Expression" /> whose <see cref="P:System.Linq.Expressions.Expression.Type" /> property value will be searched for a specific method.</param>
742 ///<param name="methodName">The name of the method.</param>
743 ///<param name="typeArguments">
744 ///An array of <see cref="T:System.Type" /> objects that specify the type parameters of the generic method.
745 ///This argument should be null when <paramref name="methodName" /> specifies a non-generic method.
747 ///<param name="arguments">An array of <see cref="T:System.Linq.Expressions.Expression" /> objects that represents the arguments to the method.</param>
748 ///<exception cref="T:System.ArgumentNullException">
749 ///<paramref name="instance" /> or <paramref name="methodName" /> is null.</exception>
750 ///<exception cref="T:System.InvalidOperationException">No method whose name is <paramref name="methodName" />, whose type parameters match <paramref name="typeArguments" />, and whose parameter types match <paramref name="arguments" /> is found in <paramref name="instance" />.Type or its base types.-or-More than one method whose name is <paramref name="methodName" />, whose type parameters match <paramref name="typeArguments" />, and whose parameter types match <paramref name="arguments" /> is found in <paramref name="instance" />.Type or its base types.</exception>
751 public static MethodCallExpression Call(Expression instance, string methodName, Type[] typeArguments, params Expression[] arguments) {
752 ContractUtils.RequiresNotNull(instance, "instance");
753 ContractUtils.RequiresNotNull(methodName, "methodName");
754 if (arguments == null) {
755 arguments = new Expression[0];
758 BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
759 return Expression.Call(instance, FindMethod(instance.Type, methodName, typeArguments, arguments, flags), arguments);
762 ///<summary>Creates a <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that represents a call to a static (Shared in Visual Basic) method by calling the appropriate factory method.</summary>
763 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" />, the <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> property set to the <see cref="T:System.Reflection.MethodInfo" /> that represents the specified static (Shared in Visual Basic) method, and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Arguments" /> property set to the specified arguments.</returns>
764 ///<param name="type">The <see cref="T:System.Type" /> that specifies the type that contains the specified static (Shared in Visual Basic) method.</param>
765 ///<param name="methodName">The name of the method.</param>
766 ///<param name="typeArguments">
767 ///An array of <see cref="T:System.Type" /> objects that specify the type parameters of the generic method.
768 ///This argument should be null when <paramref name="methodName" /> specifies a non-generic method.
770 ///<param name="arguments">An array of <see cref="T:System.Linq.Expressions.Expression" /> objects that represent the arguments to the method.</param>
771 ///<exception cref="T:System.ArgumentNullException">
772 ///<paramref name="type" /> or <paramref name="methodName" /> is null.</exception>
773 ///<exception cref="T:System.InvalidOperationException">No method whose name is <paramref name="methodName" />, whose type parameters match <paramref name="typeArguments" />, and whose parameter types match <paramref name="arguments" /> is found in <paramref name="type" /> or its base types.-or-More than one method whose name is <paramref name="methodName" />, whose type parameters match <paramref name="typeArguments" />, and whose parameter types match <paramref name="arguments" /> is found in <paramref name="type" /> or its base types.</exception>
774 public static MethodCallExpression Call(Type type, string methodName, Type[] typeArguments, params Expression[] arguments) {
775 ContractUtils.RequiresNotNull(type, "type");
776 ContractUtils.RequiresNotNull(methodName, "methodName");
778 if (arguments == null) arguments = new Expression[] { };
779 BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
780 return Expression.Call(null, FindMethod(type, methodName, typeArguments, arguments, flags), arguments);
783 ///<summary>Creates a <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that represents a method call.</summary>
784 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" />, <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" />, and <see cref="P:System.Linq.Expressions.MethodCallExpression.Arguments" /> properties set to the specified values.</returns>
785 ///<param name="instance">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> property equal to (pass null for a static (Shared in Visual Basic) method).</param>
786 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
787 ///<param name="arguments">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> that contains <see cref="T:System.Linq.Expressions.Expression" /> objects to use to populate the <see cref="P:System.Linq.Expressions.MethodCallExpression.Arguments" /> collection.</param>
788 ///<exception cref="T:System.ArgumentNullException">
789 ///<paramref name="method" /> is null.-or-<paramref name="instance" /> is null and <paramref name="method" /> represents an instance method.</exception>
790 ///<exception cref="T:System.ArgumentException">
791 ///<paramref name="instance" />.Type is not assignable to the declaring type of the method represented by <paramref name="method" />.-or-The number of elements in <paramref name="arguments" /> does not equal the number of parameters for the method represented by <paramref name="method" />.-or-One or more of the elements of <paramref name="arguments" /> is not assignable to the corresponding parameter for the method represented by <paramref name="method" />.</exception>
792 public static MethodCallExpression Call(Expression instance, MethodInfo method, IEnumerable<Expression> arguments) {
793 ContractUtils.RequiresNotNull(method, "method");
795 ReadOnlyCollection<Expression> argList = arguments.ToReadOnly();
797 ValidateMethodInfo(method);
798 ValidateStaticOrInstanceMethod(instance, method);
799 ValidateArgumentTypes(method, ExpressionType.Call, ref argList);
801 if (instance == null) {
802 return new MethodCallExpressionN(method, argList);
804 return new InstanceMethodCallExpressionN(method, instance, argList);
808 private static ParameterInfo[] ValidateMethodAndGetParameters(Expression instance, MethodInfo method) {
809 ValidateMethodInfo(method);
810 ValidateStaticOrInstanceMethod(instance, method);
812 return GetParametersForValidation(method, ExpressionType.Call);
815 private static void ValidateStaticOrInstanceMethod(Expression instance, MethodInfo method) {
816 if (method.IsStatic) {
817 if (instance != null) throw new ArgumentException(Strings.OnlyStaticMethodsHaveNullInstance, "instance");
819 if (instance == null) throw new ArgumentException(Strings.OnlyStaticMethodsHaveNullInstance, "method");
820 RequiresCanRead(instance, "instance");
821 ValidateCallInstanceType(instance.Type, method);
825 private static void ValidateCallInstanceType(Type instanceType, MethodInfo method) {
826 if (!TypeUtils.IsValidInstanceType(method, instanceType)) {
827 throw Error.InstanceAndMethodTypeMismatch(method, method.DeclaringType, instanceType);
831 private static void ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ref ReadOnlyCollection<Expression> arguments) {
832 Debug.Assert(nodeKind == ExpressionType.Invoke || nodeKind == ExpressionType.Call || nodeKind == ExpressionType.Dynamic || nodeKind == ExpressionType.New);
834 ParameterInfo[] pis = GetParametersForValidation(method, nodeKind);
836 ValidateArgumentCount(method, nodeKind, arguments.Count, pis);
838 Expression[] newArgs = null;
839 for (int i = 0, n = pis.Length; i < n; i++) {
840 Expression arg = arguments[i];
841 ParameterInfo pi = pis[i];
842 arg = ValidateOneArgument(method, nodeKind, arg, pi);
844 if (newArgs == null && arg != arguments[i]) {
845 newArgs = new Expression[arguments.Count];
846 for (int j = 0; j < i; j++) {
847 newArgs[j] = arguments[j];
850 if (newArgs != null) {
854 if (newArgs != null) {
855 arguments = new TrueReadOnlyCollection<Expression>(newArgs);
859 private static ParameterInfo[] GetParametersForValidation(MethodBase method, ExpressionType nodeKind) {
860 ParameterInfo[] pis = method.GetParametersCached();
862 if (nodeKind == ExpressionType.Dynamic) {
863 pis = pis.RemoveFirst(); // ignore CallSite argument
868 private static void ValidateArgumentCount(MethodBase method, ExpressionType nodeKind, int count, ParameterInfo[] pis) {
869 if (pis.Length != count) {
870 // Throw the right error for the node we were given
872 case ExpressionType.New:
873 throw Error.IncorrectNumberOfConstructorArguments();
874 case ExpressionType.Invoke:
875 throw Error.IncorrectNumberOfLambdaArguments();
876 case ExpressionType.Dynamic:
877 case ExpressionType.Call:
878 throw Error.IncorrectNumberOfMethodCallArguments(method);
880 throw ContractUtils.Unreachable;
885 private static Expression ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi) {
886 RequiresCanRead(arg, "arguments");
887 Type pType = pi.ParameterType;
889 pType = pType.GetElementType();
891 TypeUtils.ValidateType(pType);
892 if (!TypeUtils.AreReferenceAssignable(pType, arg.Type)) {
893 if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.GetType())) {
894 arg = Expression.Quote(arg);
896 // Throw the right error for the node we were given
898 case ExpressionType.New:
899 throw Error.ExpressionTypeDoesNotMatchConstructorParameter(arg.Type, pType);
900 case ExpressionType.Invoke:
901 throw Error.ExpressionTypeDoesNotMatchParameter(arg.Type, pType);
902 case ExpressionType.Dynamic:
903 case ExpressionType.Call:
904 throw Error.ExpressionTypeDoesNotMatchMethodParameter(arg.Type, pType, method);
906 throw ContractUtils.Unreachable;
913 private static MethodInfo FindMethod(Type type, string methodName, Type[] typeArgs, Expression[] args, BindingFlags flags) {
914 MemberInfo[] members = type.FindMembers(MemberTypes.Method, flags, Type.FilterNameIgnoreCase, methodName);
915 if (members == null || members.Length == 0)
916 throw Error.MethodDoesNotExistOnType(methodName, type);
920 var methodInfos = members.Map(t => (MethodInfo)t);
921 int count = FindBestMethod(methodInfos, typeArgs, args, out method);
924 if (typeArgs != null && typeArgs.Length > 0) {
925 throw Error.GenericMethodWithArgsDoesNotExistOnType(methodName, type);
927 throw Error.MethodWithArgsDoesNotExistOnType(methodName, type);
931 throw Error.MethodWithMoreThanOneMatch(methodName, type);
935 private static int FindBestMethod(IEnumerable<MethodInfo> methods, Type[] typeArgs, Expression[] args, out MethodInfo method) {
938 foreach (MethodInfo mi in methods) {
939 MethodInfo moo = ApplyTypeArgs(mi, typeArgs);
940 if (moo != null && IsCompatible(moo, args)) {
941 // favor public over non-public methods
942 if (method == null || (!method.IsPublic && moo.IsPublic)) {
946 // only count it as additional method if they both public or both non-public
947 else if (method.IsPublic == moo.IsPublic) {
955 private static bool IsCompatible(MethodBase m, Expression[] args) {
956 ParameterInfo[] parms = m.GetParametersCached();
957 if (parms.Length != args.Length)
959 for (int i = 0; i < args.Length; i++) {
960 Expression arg = args[i];
961 ContractUtils.RequiresNotNull(arg, "argument");
962 Type argType = arg.Type;
963 Type pType = parms[i].ParameterType;
965 pType = pType.GetElementType();
967 if (!TypeUtils.AreReferenceAssignable(pType, argType) &&
968 !(TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.GetType()))) {
975 private static MethodInfo ApplyTypeArgs(MethodInfo m, Type[] typeArgs) {
976 if (typeArgs == null || typeArgs.Length == 0) {
977 if (!m.IsGenericMethodDefinition)
980 if (m.IsGenericMethodDefinition && m.GetGenericArguments().Length == typeArgs.Length)
981 return m.MakeGenericMethod(typeArgs);
991 ///<summary>Creates a <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that represents applying an array index operator to a multi-dimensional array.</summary>
992 ///<returns>A <see cref="T:System.Linq.Expressions.BinaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.ArrayIndex" /> and the <see cref="P:System.Linq.Expressions.BinaryExpression.Left" /> and <see cref="P:System.Linq.Expressions.BinaryExpression.Right" /> properties set to the specified values.</returns>
993 ///<param name="array">An array of <see cref="T:System.Linq.Expressions.Expression" /> instances - indexes for the array index operation.</param>
994 ///<param name="indexes">An array that contains <see cref="T:System.Linq.Expressions.Expression" /> objects to use to populate the <see cref="P:System.Linq.Expressions.MethodCallExpression.Arguments" /> collection.</param>
995 public static MethodCallExpression ArrayIndex(Expression array, params Expression[] indexes) {
996 return ArrayIndex(array, (IEnumerable<Expression>)indexes);
999 ///<summary>Creates a <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that represents applying an array index operator to an array of rank more than one.</summary>
1000 ///<returns>A <see cref="T:System.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:System.Linq.Expressions.MethodCallExpression.Arguments" /> properties set to the specified values.</returns>
1001 ///<param name="array">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.MethodCallExpression.Object" /> property equal to.</param>
1002 ///<param name="indexes">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> that contains <see cref="T:System.Linq.Expressions.Expression" /> objects to use to populate the <see cref="P:System.Linq.Expressions.MethodCallExpression.Arguments" /> collection.</param>
1003 ///<exception cref="T:System.ArgumentNullException">
1004 ///<paramref name="array" /> or <paramref name="indexes" /> is null.</exception>
1005 ///<exception cref="T:System.ArgumentException">
1006 ///<paramref name="array" />.Type does not represent an array type.-or-The rank of <paramref name="array" />.Type does not match the number of elements in <paramref name="indexes" />.-or-The <see cref="P:System.Linq.Expressions.Expression.Type" /> property of one or more elements of <paramref name="indexes" /> does not represent the <see cref="T:System.Int32" /> type.</exception>
1007 public static MethodCallExpression ArrayIndex(Expression array, IEnumerable<Expression> indexes) {
1008 RequiresCanRead(array, "array");
1009 ContractUtils.RequiresNotNull(indexes, "indexes");
1011 Type arrayType = array.Type;
1012 if (!arrayType.IsArray) {
1013 throw Error.ArgumentMustBeArray();
1016 ReadOnlyCollection<Expression> indexList = indexes.ToReadOnly();
1017 if (arrayType.GetArrayRank() != indexList.Count) {
1018 throw Error.IncorrectNumberOfIndexes();
1021 foreach (Expression e in indexList) {
1022 RequiresCanRead(e, "indexes");
1023 if (e.Type != typeof(int)) {
1024 throw Error.ArgumentMustBeArrayIndexType();
1028 MethodInfo mi = array.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance);
1029 return Call(array, mi, indexList);