コード例 #1
0
ファイル: ILGeneratorEx.cs プロジェクト: AndriyMik/SimplyFast
 public static void EmitCast(this ILGenerator g, Type from, Type to)
 {
     if (from == to)
     {
         return;
     }
     if (to == typeof(object))
     {
         g.EmitBox(from);
     }
     else if (from == typeof(object))
     {
         g.EmitUnBoxAnyOrCastClass(to);
     }
     else
     {
         var method = MethodInfoEx.FindCastOperator(from, to);
         if (method != null)
         {
             g.EmitMethodCall(method);
         }
         else if (!to.IsAssignableFrom(from))
         {
             g.Emit(OpCodes.Castclass, to);
         }
     }
 }
コード例 #2
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)));
 }
コード例 #3
0
        public void FindCastFromWorks()
        {
            var t = typeof(Cast2);

            Assert.Equal(typeof(int), MethodInfoEx.FindCastFromOperator(typeof(int), t).GetParameterTypes()[0]);
            Assert.Equal(typeof(double), MethodInfoEx.FindCastFromOperator(typeof(double), t).GetParameterTypes()[0]);
            Assert.Equal(typeof(Cast1), MethodInfoEx.FindCastFromOperator(typeof(Cast1), t).GetParameterTypes()[0]);
            Assert.Null(MethodInfoEx.FindCastFromOperator(typeof(string), t));
            Assert.Null(MethodInfoEx.FindCastFromOperator(typeof(decimal), t));
        }
コード例 #4
0
        public void FindCastToWorks()
        {
            var t = typeof(Cast1);

            Assert.Equal(typeof(int), MethodInfoEx.FindCastToOperator(t, typeof(int)).ReturnType);
            Assert.Equal(typeof(double), MethodInfoEx.FindCastToOperator(t, typeof(double)).ReturnType);
            Assert.Equal(typeof(Cast2), MethodInfoEx.FindCastToOperator(t, typeof(Cast2)).ReturnType);
            Assert.Null(MethodInfoEx.FindCastToOperator(t, typeof(string)));
            Assert.Null(MethodInfoEx.FindCastToOperator(t, typeof(decimal)));
        }
コード例 #5
0
ファイル: WeakDelegate.cs プロジェクト: AndriyMik/SimplyFast
            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);
            }
コード例 #6
0
        public void FindCastWorks()
        {
            var t1 = typeof(Cast1);
            var t2 = typeof(Cast2);

            Assert.Equal(typeof(int), MethodInfoEx.FindCastOperator(t1, typeof(int)).ReturnType);
            Assert.Equal(typeof(double), MethodInfoEx.FindCastOperator(t1, typeof(double)).ReturnType);
            Assert.Null(MethodInfoEx.FindCastToOperator(t1, typeof(string)));
            Assert.Null(MethodInfoEx.FindCastToOperator(t1, typeof(decimal)));

            Assert.Equal(typeof(int), MethodInfoEx.FindCastOperator(typeof(int), t2).GetParameterTypes()[0]);
            Assert.Equal(typeof(double), MethodInfoEx.FindCastOperator(typeof(double), t2).GetParameterTypes()[0]);
            Assert.Equal(t2, MethodInfoEx.FindCastOperator(t2, t1).GetParameterTypes()[0]);
            Assert.Null(MethodInfoEx.FindCastOperator(typeof(string), t2));
            Assert.Null(MethodInfoEx.FindCastOperator(typeof(decimal), t2));

            Assert.Throws <AmbiguousMatchException>(() => MethodInfoEx.FindCastOperator(t1, t2));
        }
コード例 #7
0
ファイル: WeakDelegate.cs プロジェクト: AndriyMik/SimplyFast
            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);
            }
コード例 #8
0
ファイル: EmitEx.cs プロジェクト: AndriyMik/SimplyFast
        /// <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));
        }
コード例 #9
0
ファイル: EmitEx.cs プロジェクト: AndriyMik/SimplyFast
        /// <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));
        }
コード例 #10
0
ファイル: DynamicProxyExecutor.cs プロジェクト: yuanbeier/FZY
        protected static MethodInfo FindMethodInfo(InvokeContextBase context)
        {
            if (context != null && !string.IsNullOrEmpty(context.TypeName) &&
                !string.IsNullOrEmpty(context.MethodName))
            {
                Type type = ActivatorEx.GetType(context.TypeName);
                if (type == null)
                {
                    return(null);
                }
                MethodInfoCollection methods = GetMethodCollectionAndCache(context, type);
                if (methods != null && methods.Count > 0)
                {
                    if (methods.Count == 1)
                    {
                        return(CreateMethodEx(methods[0]));
                    }

                    object[] args = context.Arguments;
                    if (args == null)
                    {
                        args = _emptyArgs;
                        context.Arguments = args;
                    }
                    int    len           = args.Length;
                    Type[] argTypes      = context.ArgumentTypes;
                    bool   selectedTypes = true;
                    if (argTypes == null)
                    {
                        selectedTypes = false;
                        argTypes      = new Type[len];
                        for (int i = 0; i < len; i++)
                        {
                            if (args[i] != null)
                            {
                                argTypes[i] = args[i].GetType();
                            }
                        }
                    }

                    BindingFlags binding = _defaultBinding;
                    ArrayList    list    = new ArrayList(methods.Count);
                    for (int i = 0; i < methods.Count; i++)
                    {
                        if (FilterApplyMethodBaseInfo(methods[i], binding, CallingConventions.Any, argTypes))
                        {
                            list.Add(methods[i]);
                        }
                    }
                    len = list.Count;
                    if (len >= 1)
                    {
                        MethodInfoEx info = null;
                        if (len == 1)
                        {
                            info = CreateMethodEx(list[0] as MethodInfo);
                        }
                        else
                        {
                            Binder       binder     = Type.DefaultBinder;
                            MethodBase   methodBase = null;
                            MethodBase[] array      = new MethodBase[len];
                            list.CopyTo(array);
                            try
                            {
                                if (!selectedTypes)
                                {
                                    object state;
                                    methodBase = binder.BindToMethod(binding, array, ref args, null, null, null, out state);
                                }
                                else
                                {
                                    methodBase = binder.SelectMethod(binding, array, argTypes, null);
                                }
                            }
                            catch (MissingMethodException)
                            {
                                methodBase = null;
                            }
                            if (methodBase != null)
                            {
                                info = CreateMethodEx(methodBase as MethodInfo);
                            }
                        }
                        return(info);
                    }
                }
            }
            return(null);
        }
コード例 #11
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));
        }