예제 #1
0
        /// <summary>
        /// Gets the delegate associated with the LambdaExpression.
        /// Either it uses cached MethodInfo and creates delegate from it, or it will generate
        /// completely new dynamic method, store it in a cache and use it to create the delegate.
        /// </summary>
        private static Delegate GetDelegateForInterpreter(InterpreterState state, LambdaExpression lambda)
        {
            MethodInfo method;

            if (!LambdaInvoker.TryGetGenericInvokeMethod(lambda.Parameters.Count, out method) || HasByRefParameter(lambda))
            {
                return(GenerateDelegateForInterpreter(state, lambda));
            }

            Type[] signature = GetSignature(lambda);
            method = method.MakeGenericMethod(signature);
            return(ReflectionUtils.CreateDelegate(method, lambda.Type, new LambdaInvoker(lambda, state)));
        }
예제 #2
0
        /// <summary>
        /// The core of the interpreter, calling back onto itself via delegates.
        /// </summary>
        private static MethodInfo CreateDelegateForInterpreter(Type type)
        {
            Debug.Assert(type != typeof(Delegate) && typeof(Delegate).IsAssignableFrom(type));

            //
            // Get the desired signature
            //
            MethodInfo invoke = type.GetMethod("Invoke");

            ParameterInfo[] parameters = invoke.GetParameters();

            string name = "Interpreted_" + Interlocked.Increment(ref _DelegateCounter);

            Type[]       signature = CreateInterpreterSignature(parameters);
            DynamicILGen il        = Snippets.Shared.CreateDynamicMethod(name, invoke.ReturnType, signature, false);

            // Collect all arguments received by the delegate into an array
            // and pass them to the Interpreter along with the LambdaInvoker

            // LambdaInvoker
            il.EmitLoadArg(0);
            int count = parameters.Length;

            // Create the array
            il.EmitInt(count);
            il.Emit(OpCodes.Newarr, typeof(object));
            for (int i = 0; i < count; i++)
            {
                il.Emit(OpCodes.Dup);
                il.EmitInt(i);
                il.EmitLoadArg(i + 1);
                EmitExplicitCast(il, parameters[i].ParameterType, typeof(object));
                il.EmitStoreElement(typeof(object));
            }

            // Call back to interpreter
            il.EmitCall(LambdaInvoker.GetInvokeMethod());

            // Cast back to the delegate return type
            EmitExplicitCast(il, typeof(object), invoke.ReturnType);

            // And return whatever the result was.
            il.Emit(OpCodes.Ret);

            //
            // We are done (for now), finish the MethodInfo
            //
            return(il.Finish());
        }