private static MethodInfo GetMatchingMethodInfo(DetourMethodAttribute sourceAttribute, MethodInfo destinationInfo) { // we should only ever get here in case the attribute was not defined with a sourceMethodInfo, but let's check just in case. if (sourceAttribute.WasSetByMethodInfo) { return(sourceAttribute.sourceMethodInfo); } // aight, let's search by name MethodInfo[] candidates = sourceAttribute.sourceType.GetMethods(AllBindingFlags) .Where(mi => mi.Name == sourceAttribute.sourceMethodName).ToArray(); // if we only get one result, we've got our method info - if the length is zero, the method doesn't exist. if (candidates.Length == 0) { return(null); } if (candidates.Length == 1) { return(candidates.First()); } // this is where things get slightly complicated, we'll have to search by parameters. var destinationParameterTypes = destinationInfo.GetParameters().Select(pi => pi.ParameterType).ToList(); var extensionMethodType = GetExtensionMethodType(destinationInfo); if (extensionMethodType != null) { // the "this" parameter should not be used in the parameter sequence comparison destinationParameterTypes.RemoveAt(0); } candidates = candidates.Where(mi => mi.ReturnType == destinationInfo.ReturnType && (extensionMethodType == null || mi.DeclaringType == extensionMethodType) && mi.GetParameters().Select(pi => pi.ParameterType).SequenceEqual(destinationParameterTypes)).ToArray(); // if we only get one result, we've got our method info - if the length is zero, the method doesn't exist. if (candidates.Length == 0) { return(null); } if (candidates.Length == 1) { return(candidates.First()); } // if we haven't returned anything by this point there were still multiple candidates. This is theoretically impossible, // unless I missed something. return(null); }
// get source and destination MethodInfo-s from DetourMethodAttribute private static DetourPair GetDetourPairFromAttribute(DetourMethodAttribute sourceAttribute, MethodInfo destinationInfo) { // we need to get the method info of the source (usually, vanilla) method. // if it was specified in the attribute, this is easy. Otherwise, we'll have to do some digging. var sourceInfo = sourceAttribute.WasSetByMethodInfo ? sourceAttribute.sourceMethodInfo : GetMatchingMethodInfo(sourceAttribute, destinationInfo); // make sure we've got what we wanted. if (sourceInfo == null) { throw new NullReferenceException("sourceMethodInfo could not be found based on attribute"); } if (destinationInfo == null) { throw new ArgumentNullException("destinationInfo"); } return(new DetourPair(sourceInfo, destinationInfo)); }