如下代码片断展示了怎样在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方法迂回的解决,详细参见: https://blogs.msdn.microsoft.com/yirutang/2005/09/14/getmethod-limitation-regarding-generics/