Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- namespace ConsoleApp
- {
- public class MethodPattern
- {
- public string Name;
- public Type Return;
- public Type[] Parameters;
- }
- public static class Reflection
- {
- private enum TypeRestrict { NotEqual, Strong, Generic, Inherited }
- public static MethodInfo FindInstanceMethod(Type targetType, MethodPattern pattern) =>
- FindMethod(pattern, targetType.GetMethods(BindingFlags.Instance | BindingFlags.Public));
- public static MethodInfo FindStaticMethod(Type targetType, MethodPattern pattern) =>
- FindMethod(pattern, targetType.GetMethods(BindingFlags.Static | BindingFlags.Public));
- private static MethodInfo FindMethod(MethodPattern pattern, MethodInfo[] source)
- {
- var methods = source.Where(m => m.Name == pattern.Name).ToArray();
- if (pattern.Parameters?.Length > 0)
- methods = FilterMethodsByParameters(methods, pattern.Parameters);
- if (pattern.Return != null)
- return FindMethodByReturnType(methods, pattern.Return);
- return methods.FirstOrDefault();
- }
- private static MethodInfo[] FilterMethodsByParameters(MethodInfo[] source, Type[] targetParameters)
- {
- var methodByWeight = new Dictionary<MethodInfo, int>();
- foreach (var method in source)
- {
- var parameters = method.GetParameters();
- if (parameters.Length != targetParameters.Length)
- continue;
- var weight = 0;
- for (var i = 0; i < parameters.Length; i++)
- {
- var restrict = GetTypeRestrict(parameters[i].ParameterType, targetParameters[i]);
- if (restrict == TypeRestrict.NotEqual)
- {
- weight = -1;
- break;
- }
- if (restrict == TypeRestrict.Strong)
- weight += 0 + i;
- else if (restrict == TypeRestrict.Generic)
- weight += 1 + i;
- else if (restrict == TypeRestrict.Inherited)
- weight += 2 + i;
- }
- if (weight >= 0)
- methodByWeight.Add(method, weight);
- }
- return methodByWeight
- .OrderBy(m => m.Value)
- .Select(m => m.Key)
- .ToArray();
- }
- private static MethodInfo FindMethodByReturnType(MethodInfo[] source, Type returnType)
- {
- var methodByWeight = new Dictionary<MethodInfo, int>();
- foreach (var method in source)
- {
- var restrict = GetTypeRestrict(method.ReturnType, returnType);
- if (restrict == TypeRestrict.NotEqual)
- continue;
- if (restrict == TypeRestrict.Strong)
- methodByWeight.Add(method, 0);
- else if (restrict == TypeRestrict.Generic)
- methodByWeight.Add(method, 1);
- else if (restrict == TypeRestrict.Inherited)
- methodByWeight.Add(method, 2);
- }
- return methodByWeight
- .OrderBy(m => m.Value)
- .Select(m => m.Key)
- .FirstOrDefault();
- }
- private static TypeRestrict GetTypeRestrict(Type source, Type target)
- {
- if (source == target)
- return TypeRestrict.Strong;
- if (source.IsArray && target.IsArray)
- return GetTypeRestrict(source.GetElementType(), target.GetElementType());
- if (source.IsGenericParameter || source.IsGenericTypeDefinition)
- return TypeRestrict.Generic;
- if (source.IsGenericType && target.IsGenericType &&
- source.GetGenericTypeDefinition() == target.GetGenericTypeDefinition())
- return TypeRestrict.Generic;
- if (source.IsAssignableFrom(target))
- return TypeRestrict.Inherited;
- return TypeRestrict.NotEqual;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement