众所周知,反射调用,速度很慢,那怎么办?有什么方法提速么?
有啊,这不,我就介绍一下如何利用表达式树来加速反射调用。
那为什么表达式树比反射快呢?
因为,表达式树可以用Emit生成强类型委托。
好吧,让我们看看如何操作:
1. 一定要定义强类型委托,尤其是签名
/// <summary>
/// Represents a generic delegate to a function.
/// </summary>
public delegate object LateBoundFunc(object target, object[] arguments);
/// <summary>
/// Represents a generic delegate to a procedure.
/// </summary>
public delegate void LateBoundProc(object target, object[] arguments);
2. 定义好了,那我们看如何构造:
/// <summary>
/// A factory for delegates.
/// </summary>
public static class DelegateFactory
{
/// <summary>
/// Creates a delegate to the specified method.
/// </summary>
/// <typeparam name="T">Should be a <see cref="LateBoundFunc"/> or <see cref="LateBoundProc"/>.</typeparam>
/// <param name="method">The method to create the delegate for.</param>
/// <returns>The delegate.</returns>
public static T Create<T>(MethodInfo method)
{
var instanceParameter = Expression.Parameter(typeof(object), "target");
var argumentsParameter = Expression.Parameter(typeof(object[]), "arguments");
var call = Expression.Call(
Expression.Convert(instanceParameter, method.DeclaringType),
method,
CreateParameterExpressions(method, argumentsParameter)
);
var lambda = Expression.Lambda<T>(
typeof(LateBoundProc).IsAssignableFrom(typeof(T))
? call
: (Expression)Expression.Convert(call, typeof(object)),
instanceParameter,
argumentsParameter
);
return lambda.Compile();
}
private static Expression[] CreateParameterExpressions(MethodInfo method, Expression argumentsParameter)
{
return method.GetParameters().Select(
(parameter, index) =>
Expression.Convert(
Expression.ArrayIndex(argumentsParameter, Expression.Constant(index)),
parameter.ParameterType
)
).ToArray();
}
}
okay ,构造好了,如何使用呢?
public Procedure(MethodInfo info, IThreadPool threadPool)
: base(info, threadPool)
{
_theDelegate = DelegateFactory.Create<LateBoundProc>(info);
}