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 }
private static MethodBodyDisassembler CreateDisassembler(out StringWriter writer) { writer = new StringWriter(); var disassembler = new MethodBodyDisassembler(new PlainTextOutput(writer), true, new CancellationToken()); return(disassembler); }
public static string Disassemble(this MethodBody body) { var writer = new PlainTextOutput(); var dasm = new MethodBodyDisassembler(writer); dasm.Disassemble(body); return(writer.ToString()); }
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); }