如下代码片断展示了怎样在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/