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;
}
}
}
}