Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Ast / MethodCallExpression.cs / 1305376 / MethodCallExpression.cs
/* **************************************************************************** * * Copyright (c) Microsoft Corporation. * * This source code is subject to terms and conditions of the Microsoft Public License. A * copy of the license can be found in the License.html file at the root of this distribution. If * you cannot locate the Microsoft Public License, please send an email to * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound * by the terms of the Microsoft Public License. * * You must not remove this notice, or any other, from this software. * * * ***************************************************************************/ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Reflection; using System.Runtime.CompilerServices; #if SILVERLIGHT using System.Core; #endif namespace System.Linq.Expressions { ////// Represents a call to either static or an instance method. /// #if !SILVERLIGHT [DebuggerTypeProxy(typeof(Expression.MethodCallExpressionProxy))] #endif public class MethodCallExpression : Expression, IArgumentProvider { private readonly MethodInfo _method; internal MethodCallExpression(MethodInfo method) { _method = method; } internal virtual Expression GetInstance() { return null; } ////// Returns the node type of this ///. (Inherited from .) /// The public sealed override ExpressionType NodeType { get { return ExpressionType.Call; } } ///that represents this expression. /// Gets the static type of the expression that this ///represents. (Inherited from .) /// The public sealed override Type Type { get { return _method.ReturnType; } } ///that represents the static type of the expression. /// Gets the public MethodInfo Method { get { return _method; } } ///for the method to be called. /// /// Gets the public Expression Object { get { return GetInstance(); } } ///that represents the instance /// for instance method calls or null for static method cals. /// /// Gets a collection of expressions that represent arguments to the method call. /// public ReadOnlyCollectionArguments { get { return GetOrMakeArguments(); } } /// /// 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. /// /// Theproperty of the result. /// The property of the result. /// This expression if no children changed, or an expression with the updated children. public MethodCallExpression Update(Expression @object, IEnumerablearguments) { if (@object == Object && arguments == Arguments) { return this; } return Expression.Call(@object, Method, arguments); } internal virtual ReadOnlyCollection GetOrMakeArguments() { throw ContractUtils.Unreachable; } /// /// Dispatches to the specific visit method for this node type. /// protected internal override Expression Accept(ExpressionVisitor visitor) { return visitor.VisitMethodCall(this); } ////// Returns a new MethodCallExpression replacing the existing instance/args with the /// newly provided instance and args. Arguments can be null to use the existing /// arguments. /// /// This helper is provided to allow re-writing of nodes to not depend on the specific optimized /// subclass of MethodCallExpression which is being used. /// internal virtual MethodCallExpression Rewrite(Expression instance, IListargs) { throw ContractUtils.Unreachable; } #region IArgumentProvider Members Expression IArgumentProvider.GetArgument(int index) { throw ContractUtils.Unreachable; } int IArgumentProvider.ArgumentCount { get { throw ContractUtils.Unreachable; } } #endregion } #region Specialized Subclasses internal class MethodCallExpressionN : MethodCallExpression, IArgumentProvider { private IList _arguments; public MethodCallExpressionN(MethodInfo method, IList args) : base(method) { _arguments = args; } Expression IArgumentProvider.GetArgument(int index) { return _arguments[index]; } int IArgumentProvider.ArgumentCount { get { return _arguments.Count; } } internal override ReadOnlyCollection GetOrMakeArguments() { return ReturnReadOnly(ref _arguments); } internal override MethodCallExpression Rewrite(Expression instance, IList args) { Debug.Assert(instance == null); Debug.Assert(args == null || args.Count == _arguments.Count); return Expression.Call(Method, args ?? _arguments); } } internal class InstanceMethodCallExpressionN : MethodCallExpression, IArgumentProvider { private IList _arguments; private readonly Expression _instance; public InstanceMethodCallExpressionN(MethodInfo method, Expression instance, IList args) : base(method) { _instance = instance; _arguments = args; } Expression IArgumentProvider.GetArgument(int index) { return _arguments[index]; } int IArgumentProvider.ArgumentCount { get { return _arguments.Count; } } internal override Expression GetInstance() { return _instance; } internal override ReadOnlyCollection GetOrMakeArguments() { return ReturnReadOnly(ref _arguments); } internal override MethodCallExpression Rewrite(Expression instance, IList args) { Debug.Assert(instance != null); Debug.Assert(args == null || args.Count == _arguments.Count); return Expression.Call(instance, Method, args ?? _arguments); } } internal class MethodCallExpression1 : MethodCallExpression, IArgumentProvider { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider public MethodCallExpression1(MethodInfo method, Expression arg0) : base(method) { _arg0 = arg0; } Expression IArgumentProvider.GetArgument(int index) { switch (index) { case 0: return ReturnObject (_arg0); default: throw new InvalidOperationException(); } } int IArgumentProvider.ArgumentCount { get { return 1; } } internal override ReadOnlyCollection GetOrMakeArguments() { return ReturnReadOnly(this, ref _arg0); } internal override MethodCallExpression Rewrite(Expression instance, IList args) { Debug.Assert(instance == null); Debug.Assert(args == null || args.Count == 1); if (args != null) { return Expression.Call(Method, args[0]); } return Expression.Call(Method, ReturnObject (_arg0)); } } internal class MethodCallExpression2 : MethodCallExpression, IArgumentProvider { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1; // storage for the 2nd arg public MethodCallExpression2(MethodInfo method, Expression arg0, Expression arg1) : base(method) { _arg0 = arg0; _arg1 = arg1; } Expression IArgumentProvider.GetArgument(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; default: throw new InvalidOperationException(); } } int IArgumentProvider.ArgumentCount { get { return 2; } } internal override ReadOnlyCollection GetOrMakeArguments() { return ReturnReadOnly(this, ref _arg0); } internal override MethodCallExpression Rewrite(Expression instance, IList args) { Debug.Assert(instance == null); Debug.Assert(args == null || args.Count == 2); if (args != null) { return Expression.Call(Method, args[0], args[1]); } return Expression.Call(Method, ReturnObject (_arg0), _arg1); } } internal class MethodCallExpression3 : MethodCallExpression, IArgumentProvider { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1, _arg2; // storage for the 2nd - 3rd args. public MethodCallExpression3(MethodInfo method, Expression arg0, Expression arg1, Expression arg2) : base(method) { _arg0 = arg0; _arg1 = arg1; _arg2 = arg2; } Expression IArgumentProvider.GetArgument(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; case 2: return _arg2; default: throw new InvalidOperationException(); } } int IArgumentProvider.ArgumentCount { get { return 3; } } internal override ReadOnlyCollection GetOrMakeArguments() { return ReturnReadOnly(this, ref _arg0); } internal override MethodCallExpression Rewrite(Expression instance, IList args) { Debug.Assert(instance == null); Debug.Assert(args == null || args.Count == 3); if (args != null) { return Expression.Call(Method, args[0], args[1], args[2]); } return Expression.Call(Method, ReturnObject (_arg0), _arg1, _arg2); } } internal class MethodCallExpression4 : MethodCallExpression, IArgumentProvider { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1, _arg2, _arg3; // storage for the 2nd - 4th args. public MethodCallExpression4(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3) : base(method) { _arg0 = arg0; _arg1 = arg1; _arg2 = arg2; _arg3 = arg3; } Expression IArgumentProvider.GetArgument(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; case 2: return _arg2; case 3: return _arg3; default: throw new InvalidOperationException(); } } int IArgumentProvider.ArgumentCount { get { return 4; } } internal override ReadOnlyCollection GetOrMakeArguments() { return ReturnReadOnly(this, ref _arg0); } internal override MethodCallExpression Rewrite(Expression instance, IList args) { Debug.Assert(instance == null); Debug.Assert(args == null || args.Count == 4); if (args != null) { return Expression.Call(Method, args[0], args[1], args[2], args[3]); } return Expression.Call(Method, ReturnObject (_arg0), _arg1, _arg2, _arg3); } } internal class MethodCallExpression5 : MethodCallExpression, IArgumentProvider { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1, _arg2, _arg3, _arg4; // storage for the 2nd - 5th args. public MethodCallExpression5(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4) : base(method) { _arg0 = arg0; _arg1 = arg1; _arg2 = arg2; _arg3 = arg3; _arg4 = arg4; } Expression IArgumentProvider.GetArgument(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; case 2: return _arg2; case 3: return _arg3; case 4: return _arg4; default: throw new InvalidOperationException(); } } int IArgumentProvider.ArgumentCount { get { return 5; } } internal override ReadOnlyCollection GetOrMakeArguments() { return ReturnReadOnly(this, ref _arg0); } internal override MethodCallExpression Rewrite(Expression instance, IList args) { Debug.Assert(instance == null); Debug.Assert(args == null || args.Count == 5); if (args != null) { return Expression.Call(Method, args[0], args[1], args[2], args[3], args[4]); } return Expression.Call(Method, ReturnObject (_arg0), _arg1, _arg2, _arg3, _arg4); } } internal class InstanceMethodCallExpression2 : MethodCallExpression, IArgumentProvider { private readonly Expression _instance; private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1; // storage for the 2nd argument public InstanceMethodCallExpression2(MethodInfo method, Expression instance, Expression arg0, Expression arg1) : base(method) { Debug.Assert(instance != null); _instance = instance; _arg0 = arg0; _arg1 = arg1; } Expression IArgumentProvider.GetArgument(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; default: throw new InvalidOperationException(); } } int IArgumentProvider.ArgumentCount { get { return 2; } } internal override Expression GetInstance() { return _instance; } internal override ReadOnlyCollection GetOrMakeArguments() { return ReturnReadOnly(this, ref _arg0); } internal override MethodCallExpression Rewrite(Expression instance, IList args) { Debug.Assert(instance != null); Debug.Assert(args == null || args.Count == 2); if (args != null) { return Expression.Call(instance, Method, args[0], args[1]); } return Expression.Call(instance, Method, ReturnObject (_arg0), _arg1); } } internal class InstanceMethodCallExpression3 : MethodCallExpression, IArgumentProvider { private readonly Expression _instance; private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1, _arg2; // storage for the 2nd - 3rd argument public InstanceMethodCallExpression3(MethodInfo method, Expression instance, Expression arg0, Expression arg1, Expression arg2) : base(method) { Debug.Assert(instance != null); _instance = instance; _arg0 = arg0; _arg1 = arg1; _arg2 = arg2; } Expression IArgumentProvider.GetArgument(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; case 2: return _arg2; default: throw new InvalidOperationException(); } } int IArgumentProvider.ArgumentCount { get { return 3; } } internal override Expression GetInstance() { return _instance; } internal override ReadOnlyCollection GetOrMakeArguments() { return ReturnReadOnly(this, ref _arg0); } internal override MethodCallExpression Rewrite(Expression instance, IList args) { Debug.Assert(instance != null); Debug.Assert(args == null || args.Count == 3); if (args != null) { return Expression.Call(instance, Method, args[0], args[1], args[2]); } return Expression.Call(instance, Method, ReturnObject (_arg0), _arg1, _arg2); } } #endregion public partial class Expression { #region Call /// Creates a ///that represents a call to a static method that takes one argument. A ///Athat has the property equal to and the and properties set to the specified values. to set the property equal to. ///The that represents the first argument. /// /// public static MethodCallExpression Call(MethodInfo method, Expression arg0) { ContractUtils.RequiresNotNull(method, "method"); ContractUtils.RequiresNotNull(arg0, "arg0"); ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method); ValidateArgumentCount(method, ExpressionType.Call, 1, pis); arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]); return new MethodCallExpression1(method, arg0); } ///is null. Creates a ///that represents a call to a static method that takes two arguments. A ///Athat has the property equal to and the and properties set to the specified values. to set the property equal to. ///The that represents the first argument. ///The that represents the second argument. /// /// public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1) { ContractUtils.RequiresNotNull(method, "method"); ContractUtils.RequiresNotNull(arg0, "arg0"); ContractUtils.RequiresNotNull(arg1, "arg1"); ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method); ValidateArgumentCount(method, ExpressionType.Call, 2, pis); arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]); arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]); return new MethodCallExpression2(method, arg0, arg1); } ///is null. Creates a ///that represents a call to a static method that takes three arguments. A ///Athat has the property equal to and the and properties set to the specified values. to set the property equal to. ///The that represents the first argument. ///The that represents the second argument. ///The that represents the third argument. /// /// public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1, Expression arg2) { ContractUtils.RequiresNotNull(method, "method"); ContractUtils.RequiresNotNull(arg0, "arg0"); ContractUtils.RequiresNotNull(arg1, "arg1"); ContractUtils.RequiresNotNull(arg2, "arg2"); ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method); ValidateArgumentCount(method, ExpressionType.Call, 3, pis); arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]); arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]); arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]); return new MethodCallExpression3(method, arg0, arg1, arg2); } ///is null. Creates a ///that represents a call to a static method that takes four arguments. A ///Athat has the property equal to and the and properties set to the specified values. to set the property equal to. ///The that represents the first argument. ///The that represents the second argument. ///The that represents the third argument. ///The that represents the fourth argument. /// /// public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3) { ContractUtils.RequiresNotNull(method, "method"); ContractUtils.RequiresNotNull(arg0, "arg0"); ContractUtils.RequiresNotNull(arg1, "arg1"); ContractUtils.RequiresNotNull(arg2, "arg2"); ContractUtils.RequiresNotNull(arg3, "arg3"); ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method); ValidateArgumentCount(method, ExpressionType.Call, 4, pis); arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]); arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]); arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]); arg3 = ValidateOneArgument(method, ExpressionType.Call, arg3, pis[3]); return new MethodCallExpression4(method, arg0, arg1, arg2, arg3); } ///is null. Creates a ///that represents a call to a static method that takes five arguments. A ///Athat has the property equal to and the and properties set to the specified values. to set the property equal to. ///The that represents the first argument. ///The that represents the second argument. ///The that represents the third argument. ///The that represents the fourth argument. ///The that represents the fifth argument. /// /// ///is null. A public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4) { ContractUtils.RequiresNotNull(method, "method"); ContractUtils.RequiresNotNull(arg0, "arg0"); ContractUtils.RequiresNotNull(arg1, "arg1"); ContractUtils.RequiresNotNull(arg2, "arg2"); ContractUtils.RequiresNotNull(arg3, "arg3"); ContractUtils.RequiresNotNull(arg4, "arg4"); ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method); ValidateArgumentCount(method, ExpressionType.Call, 5, pis); arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]); arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]); arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]); arg3 = ValidateOneArgument(method, ExpressionType.Call, arg3, pis[3]); arg4 = ValidateOneArgument(method, ExpressionType.Call, arg4, pis[4]); return new MethodCallExpression5(method, arg0, arg1, arg2, arg3, arg4); } ///that has the property equal to and the and properties set to the specified values. /// Creates a /// Thethat represents a call to a static (Shared in Visual Basic) method. /// that represents the target method. /// The array of one or more of that represents the call arguments. /// A public static MethodCallExpression Call(MethodInfo method, params Expression[] arguments) { return Call(null, method, arguments); } ///that has the property equal to and the and properties set to the specified values. /// Creates a /// Thethat represents a call to a static (Shared in Visual Basic) method. /// that represents the target method. /// A collection of that represents the call arguments. /// A public static MethodCallExpression Call(MethodInfo method, IEnumerablethat has the property equal to and the and properties set to the specified values. arguments) { return Call(null, method, arguments); } /// /// Creates a /// Anthat represents a call to a method that takes no arguments. /// that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method). /// The that represents the target method. /// A public static MethodCallExpression Call(Expression instance, MethodInfo method) { return Call(instance, method, EmptyReadOnlyCollectionthat has the property equal to and the and properties set to the specified values. .Instance); } /// /// Creates a /// Anthat represents a method call. /// that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method). /// The that represents the target method. /// An array of one or more of that represents the call arguments. /// A public static MethodCallExpression Call(Expression instance, MethodInfo method, params Expression[] arguments) { return Call(instance, method, (IEnumerablethat has the property equal to and the and properties set to the specified values. )arguments); } /// /// Creates a /// Anthat represents a call to a method that takes two arguments. /// that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method). /// The that represents the target method. /// The that represents the first argument. /// The that represents the second argument. /// A public static MethodCallExpression Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1) { ContractUtils.RequiresNotNull(method, "method"); ContractUtils.RequiresNotNull(arg0, "arg0"); ContractUtils.RequiresNotNull(arg1, "arg1"); ParameterInfo[] pis = ValidateMethodAndGetParameters(instance, method); ValidateArgumentCount(method, ExpressionType.Call, 2, pis); arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]); arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]); if (instance != null) { return new InstanceMethodCallExpression2(method, instance, arg0, arg1); } return new MethodCallExpression2(method, arg0, arg1); } ///that has the property equal to and the and properties set to the specified values. /// Creates a /// Anthat represents a call to a method that takes three arguments. /// that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method). /// The that represents the target method. /// The that represents the first argument. /// The that represents the second argument. /// The that represents the third argument. /// A public static MethodCallExpression Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1, Expression arg2) { ContractUtils.RequiresNotNull(method, "method"); ContractUtils.RequiresNotNull(arg0, "arg0"); ContractUtils.RequiresNotNull(arg1, "arg1"); ContractUtils.RequiresNotNull(arg2, "arg2"); ParameterInfo[] pis = ValidateMethodAndGetParameters(instance, method); ValidateArgumentCount(method, ExpressionType.Call, 3, pis); arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]); arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]); arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]); if (instance != null) { return new InstanceMethodCallExpression3(method, instance, arg0, arg1, arg2); } return new MethodCallExpression3(method, arg0, arg1, arg2); } ///that has the property equal to and the and properties set to the specified values. Creates a ///that represents a call to an instance method by calling the appropriate factory method. A ///Anthat has the property equal to , the property equal to , set to the that represents the specified instance method, and set to the specified arguments. whose property value will be searched for a specific method. ///The name of the method. /// ///An array of objects that specify the type parameters of the generic method. ///This argument should be null when specifies a non-generic method. /// ///An array of objects that represents the arguments to the method. /// /// ///or is null. No method whose name is public static MethodCallExpression Call(Expression instance, string methodName, Type[] typeArguments, params Expression[] arguments) { ContractUtils.RequiresNotNull(instance, "instance"); ContractUtils.RequiresNotNull(methodName, "methodName"); if (arguments == null) { arguments = new Expression[0]; } BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; return Expression.Call(instance, FindMethod(instance.Type, methodName, typeArguments, arguments, flags), arguments); } ///, whose type parameters match , and whose parameter types match is found in .Type or its base types.-or-More than one method whose name is , whose type parameters match , and whose parameter types match is found in .Type or its base types. Creates a ///that represents a call to a static (Shared in Visual Basic) method by calling the appropriate factory method. A ///Thethat has the property equal to , the property set to the that represents the specified static (Shared in Visual Basic) method, and the property set to the specified arguments. that specifies the type that contains the specified static (Shared in Visual Basic) method. ///The name of the method. /// ///An array of objects that specify the type parameters of the generic method. ///This argument should be null when specifies a non-generic method. /// ///An array of objects that represent the arguments to the method. /// /// ///or is null. No method whose name is public static MethodCallExpression Call(Type type, string methodName, Type[] typeArguments, params Expression[] arguments) { ContractUtils.RequiresNotNull(type, "type"); ContractUtils.RequiresNotNull(methodName, "methodName"); if (arguments == null) arguments = new Expression[] { }; BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; return Expression.Call(null, FindMethod(type, methodName, typeArguments, arguments, flags), arguments); } ///, whose type parameters match , and whose parameter types match is found in or its base types.-or-More than one method whose name is , whose type parameters match , and whose parameter types match is found in or its base types. Creates a ///that represents a method call. A ///Anthat has the property equal to and the , , and properties set to the specified values. to set the property equal to (pass null for a static (Shared in Visual Basic) method). ///A to set the property equal to. ///An that contains objects to use to populate the collection. /// /// ///is null.-or- is null and represents an instance method. /// public static MethodCallExpression Call(Expression instance, MethodInfo method, IEnumerable.Type is not assignable to the declaring type of the method represented by .-or-The number of elements in does not equal the number of parameters for the method represented by .-or-One or more of the elements of is not assignable to the corresponding parameter for the method represented by . arguments) { ContractUtils.RequiresNotNull(method, "method"); ReadOnlyCollection argList = arguments.ToReadOnly(); ValidateMethodInfo(method); ValidateStaticOrInstanceMethod(instance, method); ValidateArgumentTypes(method, ExpressionType.Call, ref argList); if (instance == null) { return new MethodCallExpressionN(method, argList); } else { return new InstanceMethodCallExpressionN(method, instance, argList); } } private static ParameterInfo[] ValidateMethodAndGetParameters(Expression instance, MethodInfo method) { ValidateMethodInfo(method); ValidateStaticOrInstanceMethod(instance, method); return GetParametersForValidation(method, ExpressionType.Call); } private static void ValidateStaticOrInstanceMethod(Expression instance, MethodInfo method) { if (method.IsStatic) { if (instance != null) throw new ArgumentException(Strings.OnlyStaticMethodsHaveNullInstance, "instance"); } else { if (instance == null) throw new ArgumentException(Strings.OnlyStaticMethodsHaveNullInstance, "method"); RequiresCanRead(instance, "instance"); ValidateCallInstanceType(instance.Type, method); } } private static void ValidateCallInstanceType(Type instanceType, MethodInfo method) { if (!TypeUtils.IsValidInstanceType(method, instanceType)) { throw Error.InstanceAndMethodTypeMismatch(method, method.DeclaringType, instanceType); } } private static void ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ref ReadOnlyCollection arguments) { Debug.Assert(nodeKind == ExpressionType.Invoke || nodeKind == ExpressionType.Call || nodeKind == ExpressionType.Dynamic || nodeKind == ExpressionType.New); ParameterInfo[] pis = GetParametersForValidation(method, nodeKind); ValidateArgumentCount(method, nodeKind, arguments.Count, pis); Expression[] newArgs = null; for (int i = 0, n = pis.Length; i < n; i++) { Expression arg = arguments[i]; ParameterInfo pi = pis[i]; arg = ValidateOneArgument(method, nodeKind, arg, pi); if (newArgs == null && arg != arguments[i]) { newArgs = new Expression[arguments.Count]; for (int j = 0; j < i; j++) { newArgs[j] = arguments[j]; } } if (newArgs != null) { newArgs[i] = arg; } } if (newArgs != null) { arguments = new TrueReadOnlyCollection (newArgs); } } private static ParameterInfo[] GetParametersForValidation(MethodBase method, ExpressionType nodeKind) { ParameterInfo[] pis = method.GetParametersCached(); if (nodeKind == ExpressionType.Dynamic) { pis = pis.RemoveFirst(); // ignore CallSite argument } return pis; } private static void ValidateArgumentCount(MethodBase method, ExpressionType nodeKind, int count, ParameterInfo[] pis) { if (pis.Length != count) { // Throw the right error for the node we were given switch (nodeKind) { case ExpressionType.New: throw Error.IncorrectNumberOfConstructorArguments(); case ExpressionType.Invoke: throw Error.IncorrectNumberOfLambdaArguments(); case ExpressionType.Dynamic: case ExpressionType.Call: throw Error.IncorrectNumberOfMethodCallArguments(method); default: throw ContractUtils.Unreachable; } } } private static Expression ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi) { RequiresCanRead(arg, "arguments"); Type pType = pi.ParameterType; if (pType.IsByRef) { pType = pType.GetElementType(); } TypeUtils.ValidateType(pType); if (!TypeUtils.AreReferenceAssignable(pType, arg.Type)) { if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.GetType())) { arg = Expression.Quote(arg); } else { // Throw the right error for the node we were given switch (nodeKind) { case ExpressionType.New: throw Error.ExpressionTypeDoesNotMatchConstructorParameter(arg.Type, pType); case ExpressionType.Invoke: throw Error.ExpressionTypeDoesNotMatchParameter(arg.Type, pType); case ExpressionType.Dynamic: case ExpressionType.Call: throw Error.ExpressionTypeDoesNotMatchMethodParameter(arg.Type, pType, method); default: throw ContractUtils.Unreachable; } } } return arg; } private static MethodInfo FindMethod(Type type, string methodName, Type[] typeArgs, Expression[] args, BindingFlags flags) { MemberInfo[] members = type.FindMembers(MemberTypes.Method, flags, Type.FilterNameIgnoreCase, methodName); if (members == null || members.Length == 0) throw Error.MethodDoesNotExistOnType(methodName, type); MethodInfo method; var methodInfos = members.Map(t => (MethodInfo)t); int count = FindBestMethod(methodInfos, typeArgs, args, out method); if (count == 0) { if (typeArgs != null && typeArgs.Length > 0) { throw Error.GenericMethodWithArgsDoesNotExistOnType(methodName, type); } else { throw Error.MethodWithArgsDoesNotExistOnType(methodName, type); } } if (count > 1) throw Error.MethodWithMoreThanOneMatch(methodName, type); return method; } private static int FindBestMethod(IEnumerable methods, Type[] typeArgs, Expression[] args, out MethodInfo method) { int count = 0; method = null; foreach (MethodInfo mi in methods) { MethodInfo moo = ApplyTypeArgs(mi, typeArgs); if (moo != null && IsCompatible(moo, args)) { // favor public over non-public methods if (method == null || (!method.IsPublic && moo.IsPublic)) { method = moo; count = 1; } // only count it as additional method if they both public or both non-public else if (method.IsPublic == moo.IsPublic) { count++; } } } return count; } private static bool IsCompatible(MethodBase m, Expression[] args) { ParameterInfo[] parms = m.GetParametersCached(); if (parms.Length != args.Length) return false; for (int i = 0; i < args.Length; i++) { Expression arg = args[i]; ContractUtils.RequiresNotNull(arg, "argument"); Type argType = arg.Type; Type pType = parms[i].ParameterType; if (pType.IsByRef) { pType = pType.GetElementType(); } if (!TypeUtils.AreReferenceAssignable(pType, argType) && !(TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.GetType()))) { return false; } } return true; } private static MethodInfo ApplyTypeArgs(MethodInfo m, Type[] typeArgs) { if (typeArgs == null || typeArgs.Length == 0) { if (!m.IsGenericMethodDefinition) return m; } else { if (m.IsGenericMethodDefinition && m.GetGenericArguments().Length == typeArgs.Length) return m.MakeGenericMethod(typeArgs); } return null; } #endregion #region ArrayIndex /// Creates a ///that represents applying an array index operator to a multi-dimensional array. A ///An array ofthat has the property equal to and the and properties set to the specified values. instances - indexes for the array index operation. ///An array that contains objects to use to populate the collection. public static MethodCallExpression ArrayIndex(Expression array, params Expression[] indexes) { return ArrayIndex(array, (IEnumerable )indexes); } /// Creates a ///that represents applying an array index operator to an array of rank more than one. A ///Anthat has the property equal to and the and properties set to the specified values. to set the property equal to. ///An that contains objects to use to populate the collection. /// /// ///or is null. /// public static MethodCallExpression ArrayIndex(Expression array, IEnumerable.Type does not represent an array type.-or-The rank of .Type does not match the number of elements in .-or-The property of one or more elements of does not represent the type. indexes) { RequiresCanRead(array, "array"); ContractUtils.RequiresNotNull(indexes, "indexes"); Type arrayType = array.Type; if (!arrayType.IsArray) { throw Error.ArgumentMustBeArray(); } ReadOnlyCollection indexList = indexes.ToReadOnly(); if (arrayType.GetArrayRank() != indexList.Count) { throw Error.IncorrectNumberOfIndexes(); } foreach (Expression e in indexList) { RequiresCanRead(e, "indexes"); if (e.Type != typeof(int)) { throw Error.ArgumentMustBeArrayIndexType(); } } MethodInfo mi = array.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance); return Call(array, mi, indexList); } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HttpBindingExtension.cs
- TextEmbeddedObject.cs
- BookmarkTable.cs
- BoundConstants.cs
- PopupEventArgs.cs
- ObjectIDGenerator.cs
- SplashScreen.cs
- PeerNameResolver.cs
- DateRangeEvent.cs
- ObjectParameter.cs
- AuthenticationSection.cs
- SortedList.cs
- SmtpException.cs
- CipherData.cs
- followingsibling.cs
- FolderBrowserDialogDesigner.cs
- CollectionViewGroupInternal.cs
- UserPreferenceChangingEventArgs.cs
- EntityCodeGenerator.cs
- InputLanguageSource.cs
- ISO2022Encoding.cs
- EdgeModeValidation.cs
- ReadOnlyHierarchicalDataSource.cs
- AvTrace.cs
- XamlStream.cs
- GB18030Encoding.cs
- WebPartMenu.cs
- UriWriter.cs
- BamlStream.cs
- BamlResourceSerializer.cs
- BindingContext.cs
- SqlHelper.cs
- SelectionProviderWrapper.cs
- IResourceProvider.cs
- BufferAllocator.cs
- VerticalAlignConverter.cs
- RootBrowserWindow.cs
- RuntimeCompatibilityAttribute.cs
- NavigationProgressEventArgs.cs
- SettingsAttributeDictionary.cs
- FrameworkElementFactory.cs
- EntryWrittenEventArgs.cs
- ToolStripManager.cs
- PriorityRange.cs
- DataControlFieldHeaderCell.cs
- DBConnectionString.cs
- ComponentCommands.cs
- BaseConfigurationRecord.cs
- DecryptRequest.cs
- MsmqInputChannelBase.cs
- WebPartChrome.cs
- DefaultCommandConverter.cs
- LifetimeServices.cs
- EditingMode.cs
- Unit.cs
- DataGridViewAutoSizeColumnsModeEventArgs.cs
- CustomCategoryAttribute.cs
- Listbox.cs
- TimeSpanMinutesConverter.cs
- BookmarkManager.cs
- RegexBoyerMoore.cs
- GlyphInfoList.cs
- CultureInfo.cs
- CompositionCommandSet.cs
- ToolStripCodeDomSerializer.cs
- FreezableCollection.cs
- XpsResourcePolicy.cs
- DesignerForm.cs
- SelectionHighlightInfo.cs
- SettingsProviderCollection.cs
- IOException.cs
- EncryptedXml.cs
- Types.cs
- ResXDataNode.cs
- _SafeNetHandles.cs
- MappingModelBuildProvider.cs
- SafeCryptoHandles.cs
- TypefaceMetricsCache.cs
- RequestCachingSection.cs
- RawMouseInputReport.cs
- WindowsAuthenticationModule.cs
- AllMembershipCondition.cs
- ViewGenResults.cs
- GetPageNumberCompletedEventArgs.cs
- ToolStripPanelRenderEventArgs.cs
- ProfileGroupSettingsCollection.cs
- DoubleLink.cs
- CompiledRegexRunner.cs
- ADConnectionHelper.cs
- WindowsSpinner.cs
- ContentPresenter.cs
- QuestionEventArgs.cs
- Converter.cs
- GridProviderWrapper.cs
- securitycriticaldataformultiplegetandset.cs
- RelationshipEnd.cs
- RecommendedAsConfigurableAttribute.cs
- ComponentDispatcherThread.cs
- ContentIterators.cs
- OrderByLifter.cs