Skip to main content

C#中使用反射调用参数中包含Lambda表达式的方法

· 2 min read

如下代码片断展示了怎样在 C#中使用反射调用参数中包含 Lambda 表达式的方法: GetData(Expression<Func<ExampleEntity, bool>>), 以及根据条件动态选择无参和有参方法:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace ReflectCallGenericMethod
{
class Program
{
static void Main(string[] args)
{
Assembly assembly = Assembly.GetExecutingAssembly();
Type typeService = assembly.GetTypes()
.Where(t => t.IsClass && t.Name == "ExampleService").SingleOrDefault();
Type typeEntity = assembly.GetTypes()
.Where(t => t.IsClass && t.Name == "ExampleEntity").SingleOrDefault();

ParameterExpression paramExp = Expression.Parameter(typeEntity);
Expression expression = null;
Type[] types = Type.EmptyTypes;
object[] parameters = null;

var condition = Console.ReadLine();

if (condition.Length > 0)//如果需要过滤数据
{
Expression propExp = Expression.Property(paramExp, "ID");
Expression constExp = Expression.Constant(3);
expression = Expression.Equal(propExp, constExp);

Type delegateType = typeof(Func<,>).MakeGenericType(typeEntity, typeof(bool));
LambdaExpression lambda = Expression.Lambda(delegateType, expression, paramExp);
types = new[] { lambda.GetType() };
parameters = new[] { lambda };
}

MethodInfo methodGetInstance = typeService.GetMethod("GetInstance");
MethodInfo methodGetData = typeService.GetMethod("GetData", types);

var instanceService = methodGetInstance.Invoke(null, null);
string result = methodGetData.Invoke(instanceService, parameters) as string;

Console.WriteLine(result);
Console.ReadLine();
}
}

public class ExampleService
{
private static readonly Object _mutex = new Object();
volatile static ExampleService _instance;

public static ExampleService GetInstance()
{
if (_instance == null)
{
lock (_mutex)
{
if (_instance == null)
{
_instance = new ExampleService();
}
}
}

return _instance;
}

public string GetData()
{
return "无参方法被调用";
}

public string GetData(Expression<Func<ExampleEntity, bool>> lambda)
{
return "有参方法被调用";
}

public string GetGenericData<ExampleEntity>()
{
return "无参泛型方法被调用";
}

public string GetGenericData<ExampleEntity>(Expression<Func<ExampleEntity, bool>> lambda)
{
return "有参泛型方法被调用";
}
}

public class ExampleEntity
{
public int ID { get; set; }
public string Name { get; set; }
}
}

但这种却不能用于有 Generic Arguments 的方法,如上面代码片断中的 GetGenericData 方法,有 Generic Arguments 只能通过 GetMember 方法迂回的解决,详细参见: GetMethod limitation regarding Generics

ClustrMaps