如何通过c#反射获得"string"类型的所有方法,以及所有扩展方法,如"Aggregate", "Select"和其他方法?我知道类型大多数实现接口IEnumerable<>,但所有这些扩展方法在Enumerable类与第一个泛型参数TSource.Ok…代码:
var type = typeof(string).GetMethods(); //i get all methods string type
//I want get for this type all extensions methods like "Select" "Where"
//so i get all interfaces
type.GetInterfaces();
//ICompareble
//ICloneable
//...
//IEnumearable, but all this interfaces don't have extensions methods
//They locate in Enumerable class
//how i can use string type go to Enumerable class and get all this methods
//Somthigs like this
typeof(Enumerable).GetMethods(); //i want get all this methods but using type "string"
//Aggregate
//Select
//where
扩展方法当然可以在不同的程序集中定义,所以第一个问题是我们关心哪些程序集。我们从
开始var assemblies = GetType().Assembly
.GetReferencedAssemblies()
.Select(an => Assembly.Load(an))
.Concat(Enumerable.Repeat(GetType().Assembly, 1));
(在实例方法或属性的上下文中)获取当前程序集及其引用的所有内容,因为这是当前可用的扩展方法的可行源。其他用途将有其他起点。
现在我们需要得到所有的扩展方法:
var availableExtensionMethods = assemblies
// First get all the types
.SelectMany(asse => asse.GetExportedTypes())
// Cut out some which cannot be static classes first
.Where(t => t.IsAbstract && t.IsSealed && t.GetConstructors().Length == 0)
// Get all their methods.
.SelectMany(t => t.GetMethods())
// Restrict to just the extension methods
.Where(m => m.GetCustomAttributes().Any(ca => ca is System.Runtime.CompilerServices.ExtensionAttribute)
// An extension method must have at least one parameter, but we'll rule out being
// messed up by some strangely defined method through weird direct use of
// the ExtensionAttribute attribute
&& m.GetParameters().Length != 0)
// Get an object with the method and the first parameter we'll use below.
.Select(m => new {Method = m, FirstParam = m.GetParameters()[0]});
现在,直接根据基类(SomeMethod(this object arg)
)上的string
(SomeMethod(this string arg)
)定义的将是:
var stringExtensions = availableExtensionMethods
.Where(info => info.FirstParam.ParameterType.IsAssignableFrom(typeof(string)))
.Select(info => info.Method);
上述将包括(this IEnumerable<char> arg)
。要在泛型字符串实现(例如(this IEnumerable<T> arg)
)上获得泛型定义,我们将使用:
var stringGenericInterfaces = typeof(string).GetInterfaces()
.Where(i => i.IsGenericType)
.Select(i => i.GetGenericTypeDefinition());
var extensionsOnGenericInterfaces = from info in
availableExtensionMethods.Where(aem => aem.FirstParam.ParameterType.ContainsGenericParameters)
from inter in stringGenericInterfaces
where info.FirstParam.ParameterType.GetGenericTypeDefinition().IsAssignableFrom(inter)
select info.Method;
你可以把这些放在一起Union
得到一个批次。
我没有在这里包括约束检查。
string的扩展方法位于system_enumerable类和IEnumerable接口中。mscorlib程序集中的Linq命名空间。您可以在System中获得扩展方法的名称。
//The actual method to find all extension methods in the assembly
//that take IEnumerable<TSource> or TSource as parameters.
public static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly,Type extendedType)
{
var query = from type in assembly.GetTypes()
where type == typeof(Enumerable)
from method in type.GetMethods(BindingFlags.Static
| BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(ExtensionAttribute), false)
where (method.GetParameters()[0].ParameterType.IsGenericType
| (method.GetParameters()[0].ParameterType.ContainsGenericParameters)
select method;
return query;
}
//Get the assembly System.Linq
Assembly thisAssembly = Assembly.GetAssembly(typeof(Enumerable));
foreach (MethodInfo method in GetExtensionMethods(thisAssembly,
typeof(string)))
{
Console.WriteLine(method);
}