Ejemplo n.º 1
0
 public void GetInvokeMethodWorks()
 {
     Assert.Equal(typeof(string), MethodInfoEx.GetInvokeMethod(typeof(Func <string>)).ReturnType);
     Assert.Equal(0, MethodInfoEx.GetInvokeMethod(typeof(Func <string>)).GetParameters().Length);
     Assert.Equal(typeof(void), MethodInfoEx.GetInvokeMethod(typeof(Action <string, string>)).ReturnType);
     Assert.Equal(2, MethodInfoEx.GetInvokeMethod(typeof(Action <string, string>)).GetParameters().Length);
     Assert.Throws <ArgumentException>(() => MethodInfoEx.GetInvokeMethod(typeof(string)));
     Assert.Throws <ArgumentException>(() => MethodInfoEx.GetInvokeMethod(typeof(ClassWithInvoke)));
 }
Ejemplo n.º 2
0
            private static DynamicMethod BuildInvoke()
            {
                var invokeMethod = MethodInfoEx.GetInvokeMethod(typeof(T));
                var parameters   = invokeMethod.GetParameters();
                var args         = new Type[parameters.Length + 1];

                args[0] = typeof(WeakDelegate <T>);
                for (var i = 0; i < parameters.Length; i++)
                {
                    args[i + 1] = parameters[i].ParameterType;
                }

                var returnType = invokeMethod.ReturnType;
                var invoke     = new DynamicMethod(string.Empty,
                                                   returnType, args,
                                                   typeof(WeakDelegate <T>).Module,
                                                   MemberInfoEx.PrivateAccess);

                var il = invoke.GetILGenerator();
                //var del = il.DeclareLocal(typeof(T));
                var hasReturn   = returnType != typeof(void);
                var returnValue = hasReturn ? il.DeclareLocal(returnType) : null;

                // get enumerator
                il.Emit(OpCodes.Ldarg_0);
                il.EmitForEach(typeof(IEnumerable <T>), l =>
                {
                    for (var i = 1; i < args.Length; i++)
                    {
                        il.EmitLdarg(i);
                    }

                    il.EmitCall(OpCodes.Callvirt, invokeMethod, null);
                    if (hasReturn)
                    {
                        il.EmitStloc(returnValue);
                    }
                });

                if (hasReturn)
                {
                    il.EmitLdloc(returnValue);
                }
                il.Emit(OpCodes.Ret);

                return(invoke);
            }
Ejemplo n.º 3
0
            static ExpressionsImpl()
            {
                var invokeMethod = MethodInfoEx.GetInvokeMethod(typeof(T));

                _invokeParameters = invokeMethod.GetParameters()
                                    .ConvertAll((x, i) => Expression.Parameter(x.ParameterType, "p" + i));
                _getEnumerator = typeof(IEnumerable <T>).Method("GetEnumerator");
                _enumerator    = Expression.Variable(typeof(IEnumerator <T>), "e");

                var destroyEnumerator = Expression.Call(_enumerator, typeof(IDisposable).Method("Dispose"));

                var returnType = invokeMethod.ReturnType;
                var hasReturn  = returnType != typeof(void);
                var breakLabel = hasReturn ? Expression.Label(returnType, "br") : Expression.Label("br");
                var result     = hasReturn ? Expression.Variable(returnType, "r") : null;
                var breakExpr  = hasReturn ? Expression.Break(breakLabel, result) : Expression.Break(breakLabel);
                var moveNext   = Expression.Call(_enumerator, typeof(IEnumerator).Method("MoveNext"));
                var current    = Expression.Property(_enumerator, typeof(IEnumerator <T>).Property("Current"));
                // ReSharper disable once CoVariantArrayConversion
                var invoke = (Expression)Expression.Invoke(current, _invokeParameters);

                if (hasReturn)
                {
                    invoke = Expression.Assign(result, invoke);
                }
                var ifNotMoveNext = Expression.IfThenElse(moveNext, invoke, breakExpr);
                var loop          = (Expression)Expression.Loop(ifNotMoveNext, breakLabel);

                if (hasReturn)
                {
                    loop = Expression.Block(new[] { result },
                                            Expression.Assign(result, Expression.Default(returnType)),
                                            loop);
                }

                _invokeLoop = Expression.TryFinally(loop, destroyEnumerator);
            }
Ejemplo n.º 4
0
        /// <summary>
        /// Creates dynamic method that matches delegateType
        /// </summary>
        public static DynamicMethod CreateMethod(this Type owner, Type delegateType, string name = null, bool skipVisibility = false)
        {
            var invoke = MethodInfoEx.GetInvokeMethod(delegateType);

            return(new DynamicMethod(name ?? string.Empty, invoke.ReturnType, invoke.GetParameterTypes(), owner, skipVisibility));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Creates dynamic method that matches delegateType
        /// </summary>
        public static DynamicMethod CreateMethod(this Module m, Type delegateType, string name, bool skipVisibility = false)
        {
            var invoke = MethodInfoEx.GetInvokeMethod(delegateType);

            return(new DynamicMethod(name, invoke.ReturnType, invoke.GetParameterTypes(), m, skipVisibility));
        }
Ejemplo n.º 6
0
        /// <summary>
        ///     Converts lambda input and return types
        /// </summary>
        /// <param name="lambda">lambda to convert</param>
        /// <param name="delegateType">new delegate type</param>
        /// <returns></returns>
        public static LambdaExpression Convert(LambdaExpression lambda, Type delegateType)
        {
            if (lambda.Type == delegateType)
            {
                return(lambda);
            }

            var invoke = MethodInfoEx.GetInvokeMethod(delegateType);

            var result           = invoke.ReturnType;
            var invokeParameters = invoke.GetParameters();
            var parameters       = invokeParameters.ConvertAll(p => p.ParameterType);

            if (parameters.Length < lambda.Parameters.Count)
            {
                throw new ArgumentException("Parameters count is less than lambdas", nameof(delegateType));
            }

            if (SignatureMatch(lambda, result, parameters))
            {
                // Fixes stupid issue in .Net framework - byref delegates are not convertible, so can't compile byref =\
                return(delegateType == null ? lambda : Expression.Lambda(delegateType, lambda.Body, lambda.Parameters));
            }

            var newParameters = parameters.ConvertAll(Expression.Parameter);

            var variables      = new List <ParameterExpression>();
            var inConversions  = new List <Expression>();
            var outConversions = new List <Expression>();
            var call           = new Expression[lambda.Parameters.Count];

            for (var i = 0; i < lambda.Parameters.Count; i++)
            {
                var lambdaParam = lambda.Parameters[i];
                var newParam    = newParameters[i];
                if (lambdaParam.Type == newParam.Type)
                {
                    // no conversion
                    call[i] = newParam;
                    continue;
                }
                if (!(newParam.IsByRef && lambdaParam.IsByRef))
                {
                    //call[i] = newParam.TypeAs(lambdaParam.Type);
                    call[i] = newParam.Convert(lambdaParam.Type);
                    continue;
                }
                var variable = Expression.Variable(lambdaParam.Type);
                call[i] = variable;
                variables.Add(variable);
                inConversions.Add(invokeParameters[i].IsOut
                    ? variable.Assign(Expression.Default(lambdaParam.Type))
                    : variable.Assign(newParam.Convert(lambdaParam.Type)));
                outConversions.Add(newParam.Assign(variable.Convert(newParam.Type)));
            }
            var newBody = Inline(lambda, call);

            if (variables.Count == 0)
            {
                if (result == newBody.Type)
                {
                    return(Expression.Lambda(delegateType, newBody, newParameters));
                }
                if (result == typeof(void) || newBody.Type == typeof(void))
                {
                    newBody = Expression.Block(newBody, Expression.Default(result));
                }
                else
                {
                    newBody = newBody.Convert(result);
                }
            }
            else
            {
                if (result == typeof(void) || newBody.Type == typeof(void))
                {
                    outConversions.Add(Expression.Default(result));
                }
                else
                {
                    var resultVariable = Expression.Variable(result);
                    newBody = Expression.Assign(resultVariable, newBody.Convert(result));
                    variables.Add(resultVariable);
                    outConversions.Add(resultVariable);
                }
                inConversions.Add(newBody);
                newBody = Expression.Block(variables, inConversions.Concat(outConversions));
            }

            return(Expression.Lambda(delegateType, newBody, newParameters));
        }