Список методов и Extension методов
Однажды обсуждая возможности рефлексии в C# обнаружил некоторую проблему, с получением списка методов, которыми располагает класс. На первый взгляд все очень просто. В пространстве имен System.Reflection есть функционал, доступный разработчику, для получения списка методов класса или списка членов, их применение проиллюстрировано ниже:
public void ListMethodsAndMembers()
{ Type t = this.GetType(); MethodInfo[] mi = t.GetMethods(); foreach (MethodInfo m in mi) Console.WriteLine("Method: {0}", m.Name); MemberInfo[] members = t.GetMembers(); foreach (MemberInfo m in members) Console.WriteLine("Member: {0}", m.Name);
}
Всё работает, безупречно, и даже довольно быстро, не смотря на то, что это рефлекися...
Всё бы хорошо, но что делать, если в экземпляре класса можно вызвать экстеншн метод, если он доступен в автоподсказке студии, а вот в данном списке он отсутствует?
public void ListMethodsAndMembers()
{ Type t = this.GetType(); MethodInfo[] mi = t.GetMethods(); foreach (MethodInfo m in mi) Console.WriteLine("Method: {0}", m.Name); MemberInfo[] members = t.GetMembers(); foreach (MemberInfo m in members) Console.WriteLine("Member: {0}", m.Name);
}
Всё работает, безупречно, и даже довольно быстро, не смотря на то, что это рефлекися...
Всё бы хорошо, но что делать, если в экземпляре класса можно вызвать экстеншн метод, если он доступен в автоподсказке студии, а вот в данном списке он отсутствует?
(Все три метода ExMethodX - Extension, как видите доступны в студийной автоподсказке)
Вся проблема в том, что мы не видим методов расширения в списке GetMethods() .
После нескольких минут сёрфа по инету и чтения MSDN я нашел решение данной проблемы, и, не смотря на то, что такой вариант тяжеловатый, иногда можно обратиться и к нему.
Решение "В ЛОБ", но лучшего пока не нашел, как найду, снова выложу в блог. Смысл решения в следующем методе:
private static IEnumerable<MethodInfo> GetExtensionMethods(Type extendedType)
{
Assembly assembly = extendedType.Assembly;
var query = from type in assembly.GetTypes()
where type.IsSealed && !type.IsGenericType && !type.IsNested
from method in type.GetMethods(BindingFlags.Static
| BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(ExtensionAttribute), false)
where method.GetParameters()[0].ParameterType == extendedType
select method;
return query;
}
Итак, вот иллюстрация:
class Program
{ static void Main(string[] args) { var holder = new Holder(); holder.ListMethods(); holder.ListExtensionMethods(); Console.ReadKey(); }
} Реализация класса Holder
namespace Extensions_via_reflection
{
public class Holder
{
public Holder()
{
Console.WriteLine("Insatce of Holder created");
}
public int InnerMethod()
{
Console.WriteLine("public InnerMethod called");
return 0;
}
public void innerMethod()
{
Console.WriteLine("private innerMethod called");
}
public void ListMethods()
{
Type t = this.GetType();
MethodInfo[] mi = t.GetMethods();
foreach (MethodInfo m in mi)
Console.WriteLine("Method: {0}", m.Name);
}
public void ListExtensionMethods()
{
foreach (var m in GetExtensionMethods(GetType()))
Console.WriteLine("EXTENSION Method: {0}", m.Name);
}
private static IEnumerable GetExtensionMethods(Type extendedType)
{
Assembly assembly = extendedType.Assembly;
var query = from type in assembly.GetTypes()
where type.IsSealed && !type.IsGenericType && !type.IsNested
from method in type.GetMethods(BindingFlags.Static
| BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(ExtensionAttribute), false)
where method.GetParameters()[0].ParameterType == extendedType
select method;
return query;
}
}
}
И реализация класса с extension методами для Holder
public static class HolderExtensions
{
public static void ExMethod(this Holder holder)
{
Console.WriteLine("Extension method ExMethod called");
}
public static void ExMethod1(this Holder holder)
{
Console.WriteLine("Extension method ExMethod1 called");
}
public static void ExMethod2(this Holder holder)
{
Console.WriteLine("Extension method ExMethod2 called");
}
}
Результат
Комментариев нет:
Отправить комментарий