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

时间:2016-11-12 23:48:42

标签: c# string visual-studio reflection typeof

如何获取“string”类型的所有方法,使用所有扩展方法,如“聚合”,“选择”和其他c#反射?我知道类型大多数实现接口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

2 个答案:

答案 0 :(得分:1)

扩展方法当然可以在不同的程序集中定义,因此第一个问题是我们关心的程序集。我们将从

开始
var assemblies = GetType().Assembly
    .GetReferencedAssemblies()
    .Select(an => Assembly.Load(an))
    .Concat(Enumerable.Repeat(GetType().Assembly, 1));

to(在实例方法或属性的上下文中)获取当前程序集及其引用的所有内容,因为这是可用的扩展方法的可行来源。其他用途将有其他起点。

现在我们需要获得所有扩展方法:

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

现在,基类(string)上直接用SomeMethod(this string arg)SomeMethod(this object 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这些来获得很多。

尽管如此,我还没有对限制进行检查。

答案 1 :(得分:0)

string的扩展方法位于Enumerable类和IEnumerable接口中,它们位于mscorlib程序集的System.Linq命名空间中。 您可以通过以下方式获取System.Linq中扩展方法的名称:

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