【问题标题】:All extensions methods for type string字符串类型的所有扩展方法
【发布时间】:2017-03-26 22:12:29
【问题描述】:

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

【问题讨论】:

  • 我认为您很容易为您的问题发布可重现的代码,以便我们可以在我们的机器上对其进行测试..
  • 这个 [link]stackoverflow.com/questions/299515/… 方法不起作用,因为他使用第一个参数 typeof(string),在我的版本中,这个方法有第一个参数通用 TSource。

标签: c# string visual-studio reflection typeof


【解决方案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]});

现在,根据基类 (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这些一起来获得很多。

不过,我没有在此处包含对约束的检查。

【讨论】:

  • 非常感谢你,它的工作。我无法评估您的答案,因为我名声不好。这是我的第一个问题,我有“-2”,不知道为什么,可能是因为我的英语不好:))
【解决方案2】:

字符串的扩展方法位于 mscorlib 程序集的 System.Linq 命名空间中的 Enumerable 类和 IEnumerable 接口中。 您可以通过以下方式获取 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);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-13
    • 2021-09-10
    • 2011-07-09
    相关资源
    最近更新 更多