public static MethodCallExpression Call(
Type type, // 包含目标方法的类型
string methodName, // 方法名称
Type[]? typeArguments, // 泛型方法的类型参数(非泛型方法为 null)
params Expression[]? arguments // 方法参数的表达式数组
);
这个方法是 C# 中 System.Linq.Expressions.Expression
类的静态方法,用于创建一个表示调用静态方法的表达式树节点。
参数详解
-
type
- 类型:
Type
- 描述:指定包含目标方法的类或接口类型。
- 示例:
typeof(Math)
(用于调用Math
类的静态方法)。
- 类型:
-
methodName
- 类型:
string
- 描述:目标方法的名称(区分大小写)。
- 示例:
"Sqrt"
(对应Math.Sqrt
方法)。
- 类型:
-
typeArguments
- 类型:
Type[]?
(可空的类型数组) - 描述:
- 对于泛型方法,传递泛型类型参数(如
new[] { typeof(int) }
)。 - 对于非泛型方法,传
null
或省略此参数。
- 对于泛型方法,传递泛型类型参数(如
- 示例
// 泛型方法 List<T>.Add(T item) typeof(List<>).MakeGenericType(typeof(int)) // List<int> typeof(List<int>).GetMethod("Add") // Add(int item)
- 类型:
-
arguments
- 类型:
params Expression[]?
(可变参数的表达式数组) - 描述:传递给目标方法的参数表达式。
- 示例:
Expression.Constant(16.0) // 表示常量值 16.0
返回值
- 类型:
MethodCallExpression
- 描述:表示静态方法调用的表达式树节点,可用于构建更复杂的表达式或直接编译执行。
使用场景
1. 调用静态非泛型方法
// 创建表达式:Math.Sqrt(16.0)
var callExpr = Expression.Call(
typeof(Math), // 类型
"Sqrt", // 方法名
null, // 非泛型方法,传 null
Expression.Constant(16.0) // 参数:16.0
);
// 编译并执行
double result = Expression.Lambda<Func<double>>(callExpr).Compile()();
Console.WriteLine(result); // 输出: 4
2. 调用静态泛型方法
// 创建表达式:Convert.ChangeType("42", typeof(int))
var callExpr = Expression.Call(
typeof(Convert), // 类型
"ChangeType", // 方法名
null, // 非泛型方法签名(但 ChangeType 有泛型重载,需明确指定参数类型)
Expression.Constant("42"), // 第一个参数:"42"
Expression.Constant(typeof(int)) // 第二个参数:typeof(int)
);
// 编译并执行
int result = (int)Expression.Lambda<Func<object>>(callExpr).Compile()();
Console.WriteLine(result); // 输出: 42
3. 构建复杂查询条件
在 ORM 框架(如 Entity Framework)中动态生成查询:
// 创建表达式:queryable.Where(x => x.Name.Contains("test"))
ParameterExpression param = Expression.Parameter(typeof(MyEntity), "x");
MethodCallExpression containsCall = Expression.Call(
Expression.Property(param, "Name"), // x.Name
"Contains", // 方法名
null, // 非泛型
Expression.Constant("test") // 参数:"test"
);
// 构建 Lambda 表达式:x => x.Name.Contains("test")
Expression<Func<MyEntity, bool>> lambda =
Expression.Lambda<Func<MyEntity, bool>>(containsCall, param);
// 应用到查询
var results = dbContext.MyEntities.Where(lambda).ToList();
注意事项
-
方法重载匹配
- 此方法会根据
typeArguments
和arguments
的类型自动匹配对应的方法重载。 - 若存在歧义(如多个重载都匹配参数类型),需手动获取
MethodInfo
并使用Expression.Call(MethodInfo method, params Expression[] arguments)
重载。
- 此方法会根据
-
泛型方法处理
- 对于开放泛型类型(如
List<>
),需先通过MakeGenericType
构建封闭类型(如List<int>
)。 - 示例:
Type listType = typeof(List<>).MakeGenericType(typeof(int)); // List<int> MethodInfo addMethod = listType.GetMethod("Add");
-
性能考虑
表达式树的编译和执行比直接方法调用慢,适合动态生成代码的场景(如 ORM、动态查询)。
- 对于开放泛型类型(如
相关 API
Expression.Call(MethodInfo method, params Expression[] arguments)
:通过MethodInfo
显式指定方法。Expression.Call(Expression instance, MethodInfo method, params Expression[] arguments)
:调用实例方法(需提供实例表达式)。Expression.Lambda
:将表达式树转换为可执行的委托。
通过 Expression.Call
,可以在运行时动态构建方法调用逻辑,为框架开发和高级应用提供强大支持。