来给反射调用加加速(1):利用表达式树

众所周知,反射调用,速度很慢,那怎么办?有什么方法提速么?

有啊,这不,我就介绍一下如何利用表达式树来加速反射调用。

 

那为什么表达式树比反射快呢?

因为,表达式树可以用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);
            }

 

 

posted @ 2010-01-24 11:21  primeli  阅读(518)  评论(0编辑  收藏  举报