Możemy także zdecydować się czy odfiltrować metody generowane dla automatycznych właściwości.
Metody są zwracane w sposób posortowany najpierw po typie (od najmłodszego do bazowego), a dalej w kolejności występowania.
I znowu problemy. Tym razem przypuśćmy, że mamy metodę publiczną zdefiniowaną w klasie A, mamy klasę B wywodzącą się z A. Pobieramy tą metodę z typu A i z typu B, chcemy ustalić, że są takie same. Ich porównanie nic nie da. Ich
ReflectedType
są różne. Pozostaje więc ręcznie wykazać, że metody mają takie same sygnatury. Z całego dobrodziejswta MethodInfo
decydujemy się nazwy i parametry. Niestety, okaże się parametrów też nie możemy porównać. Żeby było śmieszniej różnią się tylko MetadataToken
. Z całego dobrodziejstwa ParameterInfo
decydujemy się na porównanie ParameterType
. Bez problemu radzimy sobie z rozróżnieniem parametrów z out, in, ref
. Zgodnie z moimi testami wszystko działa. Ale nie wykluczam, że z uwagi na to, że do porównania nie biorę wszystkich elementów istnieją takie których porównanie zwróci fałszywy wynik.Kod:
public static IEnumerable<type> GetBaseTypes(this Type a_type, bool a_with_this = false) { if (a_with_this) yield return a_type; Type t = a_type; while (t.BaseType != null) { t = t.BaseType; yield return t; } } public static IEnumerable<methodinfo> GetBaseDefinitions(this MethodInfo a_mi, bool a_with_this = false) { if (a_with_this) yield return a_mi; MethodInfo t = a_mi; while ((t.GetBaseDefinition() != null) && (t.GetBaseDefinition() != t)) { t = t.GetBaseDefinition(); yield return t; } } public static bool IsDerivedFrom(this MethodInfo a_mi, MethodInfo a_base, bool a_with_this = false) { if (a_mi.Name != a_base.Name) return false; if (a_mi.DeclaringType == a_base.DeclaringType) { if (!a_mi.GetParameters().Select(p => p.ParameterType).SequenceEqual( a_base.GetParameters().Select(p => p.ParameterType))) { return false; } return a_with_this; } return a_mi.GetBaseDefinitions().Contains(a_base); } public static IEnumerable<MethodInfo> GetAllMethods(this Type a_type, bool a_include_autogenerated = false) { List<MethodInfo> result = new List<MethodInfo>(); foreach (var t in a_type.GetBaseTypes(true)) { if (t == typeof(Object)) break; if (t == typeof(ValueType)) break; MethodInfo[] methods = t.GetMethods( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var method in methods.Reverse()) { if (method.IsDefined(typeof(CompilerGeneratedAttribute), true) && !a_include_autogenerated) { continue; } if (method.IsAbstract) continue; if (result.All(m => !m.IsDerivedFrom(method, true))) { result.Add(method); yield return method; } } } }
Brak komentarzy:
Prześlij komentarz