类型字符串的所有扩展方法

本文关键字:扩展 方法 字符串 类型 | 更新日期: 2023-09-27 18:17:34

如何通过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);
    }