public static MethodInfo GetLocalFunction(Type type, MethodInfo method, string localMemberName)
        {
#if !PORTABLE
            if (type.IsProxy())
            {
                type = type.BaseType;
            }

            string expectedName = String.Format("<{0}>g__{1}|", method.Name, localMemberName);

            MethodBody body             = method.GetMethodBody();
            var        disasembledBody  = MethodBodyDisassembler.DisassembleMethodInfo(method);
            var        callInstructions = disasembledBody.Where(instr => instr.OpCode == System.Reflection.Emit.OpCodes.Call).ToArray();
            MethodInfo localMethod      = null;
            foreach (var instruction in callInstructions)
            {
                MethodBase methodBase = type.Module.ResolveMethod(instruction.Operand.Int);
                if (methodBase != null && methodBase.DeclaringType == type && methodBase.Name.StartsWith(expectedName))
                {
                    localMethod = methodBase as MethodInfo;
                    break;
                }
            }

            if (localMethod == null)
            {
                throw new MissingMemberException(BuildMissingLocalFunctionMessage(type, method, localMemberName));
            }

            return(localMethod);
#else
            return(null);
#endif
        }
Example #2
0
        private static MethodBodyDisassembler CreateDisassembler(out StringWriter writer)
        {
            writer = new StringWriter();
            var disassembler = new MethodBodyDisassembler(new PlainTextOutput(writer), true, new CancellationToken());

            return(disassembler);
        }
Example #3
0
        public static string Disassemble(this MethodBody body)
        {
            var writer = new PlainTextOutput();
            var dasm   = new MethodBodyDisassembler(writer);

            dasm.Disassemble(body);
            return(writer.ToString());
        }
Example #4
0
 private static void DisassembleType(TypeDefinition type, MethodBodyDisassembler disassembler, StringWriter writer)
 {
     foreach (var method in type.Methods.Where(method => method.HasBody))
     {
         writer.WriteLine(method.FullName.ToString());
         disassembler.Disassemble(method.Body, null);
         writer.WriteLine();
         writer.WriteLine();
     }
 }
        public static MethodInfo GetLocalFunction(Type type, MethodInfo method, string localMemberName, Type[] localFunctionGenericTypes)
        {
#if !PORTABLE
            if (type.IsProxy())
            {
                type = type.BaseType;
            }

            string expectedName = String.Format("<{0}>g__{1}|", method.Name, localMemberName);

            MethodBody body             = method.GetMethodBody();
            var        disasembledBody  = MethodBodyDisassembler.DisassembleMethodInfo(method);
            var        callInstructions = disasembledBody.Where(instr => instr.OpCode == System.Reflection.Emit.OpCodes.Call).ToArray();
            MethodInfo localMethod      = null;
            foreach (var instruction in callInstructions)
            {
                MethodBase methodBase = null;
                try
                {
                    methodBase = type.Module.ResolveMethod(instruction.Operand.Int);
                }
                catch (Exception)
                {
                    //The exception is captured when the metadata token refers generic method.
                    //Do not handle the exception since there is no way to know in advance if the metadata token refers non-generic or generic method.
                }

                if (methodBase == null && localFunctionGenericTypes != null)
                {
                    try
                    {
                        methodBase = type.Module.ResolveMethod(instruction.Operand.Int, null, localFunctionGenericTypes);

                        //This additional check is required because if we have function<T1,T2> and pass localFunctionGenericTypes weith <T1,T2,T3>
                        //the method ResolveMethod returns function<T1,T2> even if the typenames are less than those in the provided array.
                        if (methodBase != null)
                        {
                            Type[] genericArgDefinition = methodBase.GetGenericArguments();
                            if (genericArgDefinition.Length != localFunctionGenericTypes.Length)
                            {
                                methodBase = null;
                            }
                        }
                    }
                    catch (Exception)
                    {
                        //The exception is captured when the metadata token refers non-generic method.
                        //Do not handle the exception since there is no way to know in advance if the metadata token refers non-generic or generic method.
                    }
                }

                if (methodBase != null && methodBase.DeclaringType == type && methodBase.Name.StartsWith(expectedName))
                {
                    localMethod = methodBase as MethodInfo;
                    break;
                }
            }

            if (localMethod == null)
            {
                if (localFunctionGenericTypes == null)
                {
                    throw new MissingMemberException(BuildMissingLocalFunctionMessage(type, method, localMemberName));
                }
                else
                {
                    int         methodGenericArgCount          = method.GetGenericArguments().Length;
                    List <Type> userFriendlyLocalFunctionTypes = new List <Type>();
                    for (int index = methodGenericArgCount; index < localFunctionGenericTypes.Length; index++)
                    {
                        userFriendlyLocalFunctionTypes.Add(localFunctionGenericTypes[index]);
                    }

                    string userFriendlyName = String.Join(".", method.ToString(), localMemberName);

                    throw new MissingMemberException(BuildGenericMethodNonMatchingTypesMessage(type, userFriendlyName, userFriendlyLocalFunctionTypes.ToArray()));
                }
            }

            return(localMethod);
#else
            return(null);
#endif
        }
        public static MethodInfo GetLocalFunction(Type type, MethodInfo method, string localMemberName, Type[] localFunctionGenericTypes, string originalMethodName = null)
        {
            MethodInfo localMethod = null;

#if !PORTABLE
            AsyncStateMachineAttribute asyncStateMachineAttribute =
                method.CustomAttributes.Select(
                    attributeData =>
            {
                AsyncStateMachineAttribute attribute = null;
                if (attributeData.AttributeType == typeof(AsyncStateMachineAttribute))
                {
                    attribute = (AsyncStateMachineAttribute)method.GetCustomAttribute(attributeData.AttributeType);
                }
                return(attribute);
            }).FirstOrDefault();

            if (asyncStateMachineAttribute != null)
            {
                var asyncMethodName = method.Name;
                // check for existing async state machine method "MoveNext"
                method = asyncStateMachineAttribute.StateMachineType.GetMethod("MoveNext", BindingFlags.NonPublic | BindingFlags.Instance);
                if (method != null)
                {
                    // search for local method inside "MoveNext"
                    localMethod = GetLocalFunction(type, method, localMemberName, localFunctionGenericTypes, asyncMethodName);
                }
            }
            else
            {
                if (type.IsProxy())
                {
                    type = type.BaseType;
                }

                string expectedName = String.Format("<{0}>g__{1}|", string.IsNullOrEmpty(originalMethodName) ? method.Name : originalMethodName, localMemberName);

                MethodBody body             = method.GetMethodBody();
                var        disasembledBody  = MethodBodyDisassembler.DisassembleMethodInfo(method);
                var        callInstructions = disasembledBody.Where(instr => instr.OpCode == System.Reflection.Emit.OpCodes.Call).ToArray();

                foreach (var instruction in callInstructions)
                {
                    MethodBase methodBase = null;
                    try
                    {
                        methodBase = type.Module.ResolveMethod(instruction.Operand.Int);
                    }
                    catch (Exception)
                    {
                        //The exception is captured when the metadata token refers generic method.
                        //Do not handle the exception since there is no way to know in advance if the metadata token refers non-generic or generic method.
                    }

                    if (methodBase == null && localFunctionGenericTypes != null)
                    {
                        try
                        {
                            methodBase = type.Module.ResolveMethod(instruction.Operand.Int, null, localFunctionGenericTypes);

                            //This additional check is required because if we have function<T1,T2> and pass localFunctionGenericTypes weith <T1,T2,T3>
                            //the method ResolveMethod returns function<T1,T2> even if the typenames are less than those in the provided array.
                            if (methodBase != null)
                            {
                                Type[] genericArgDefinition = methodBase.GetGenericArguments();
                                if (genericArgDefinition.Length != localFunctionGenericTypes.Length)
                                {
                                    methodBase = null;
                                }
                            }
                        }
                        catch (Exception)
                        {
                            //The exception is captured when the metadata token refers non-generic method.
                            //Do not handle the exception since there is no way to know in advance if the metadata token refers non-generic or generic method.
                        }
                    }

                    if (methodBase != null && methodBase.DeclaringType == type && methodBase.Name.StartsWith(expectedName))
                    {
                        localMethod = methodBase as MethodInfo;
                        break;
                    }
                }

                if (localMethod == null)
                {
                    if (localFunctionGenericTypes == null)
                    {
                        throw new MissingMemberException(BuildMissingLocalFunctionMessage(type, method, localMemberName));
                    }
                    else
                    {
                        int         methodGenericArgCount          = method.GetGenericArguments().Length;
                        List <Type> userFriendlyLocalFunctionTypes = new List <Type>();
                        for (int index = methodGenericArgCount; index < localFunctionGenericTypes.Length; index++)
                        {
                            userFriendlyLocalFunctionTypes.Add(localFunctionGenericTypes[index]);
                        }

                        string userFriendlyName = String.Join(".", method.ToString(), localMemberName);

                        throw new MissingMemberException(BuildGenericMethodNonMatchingTypesMessage(type, userFriendlyName, userFriendlyLocalFunctionTypes.ToArray()));
                    }
                }
            }
#endif

            return(localMethod);
        }