我们的 UI 系统可以从 MethodInfo 生成表单。在 System.Linq.Expressions 之前,我们使用反射(方法 1)获取 MethodInfo:
MethodInfo info = typeof(ExtensionTestClass).GetMethod("InstanceMethod", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(string) }, null);
不好的地方在于,如果我们更改了 InstanceMethod 的签名或名称,代码仍然可以编译。
输入表达式。现在我们这样做(方法2):
MethodInfo info = GetMethod<ExtensionTestClass>(x => x.InstanceMethod("defaultValue", "defaultValue"));
或者这个(方法3):
MethodInfo info = GetMethod<ExtensionTestClass, string, string>(x => x.InstanceMethod);
语法“更好”,我们得到智能感知,如果方法不存在或签名不匹配,我们会得到编译错误。但是,方法 2 和方法 3 比反射慢大约 10 到 20 倍。
一些数字(用秒表测量):
单次调用: 方法 1:.0000565 方法 2:.0004272 方法 3:.0019222
100000 次调用: 方法 1:.1171071 方法 2:1.5648544 方法 3:2.0602607
我们实际上并没有编译或执行表达式,如果有人对性能差异有解释,我很感兴趣。
更新:GetMethod<> 代码:
方法二:
public static MethodInfo GetMethod<T>(Expression<Action<T>> target)
{
MethodCallExpression exp = target.Body as MethodCallExpression;
if (exp != null)
{
return exp.Method;
}
return null;
}
方法三:
public static MethodInfo GetMethod<T, A1, A2>(Expression<Func<T, Action<A1, A2>>> expression)
{
var lambdaExpression = (LambdaExpression)expression;
var unaryExpression = (UnaryExpression)lambdaExpression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
return (MethodInfo)methodInfoExpression.Value;
}