-2

How get all methods for "string" Type, with all extensions methods like "Aggregate", "Select" and other by c# reflection? I know that type most implement interface IEnumerable<>, but all this extension methods in Enumerable class with first generic parametr TSource.Ok... code:

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
itihonov
  • 81
  • 1
  • 7
  • 1
    I think it is easy for you to post a reproducable code for your problem so that we can test it at our machines.. – L.B Nov 12 '16 at 23:55
  • this [link]http://stackoverflow.com/questions/299515/reflection-to-identify-extension-methods method don't work because he use first parametr typeof(string), in my version this methods have first parametr generic TSource. – itihonov Nov 13 '16 at 00:25

2 Answers2

1

Extension methods can of course be defined in different assemblies, so the first question is which assemblies we care about. We'll start with

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

to (in the context of an instance method or property) get the current assembly and all that it references, as that is the feasible source for extension methods available there and then. Other uses will have other starting points.

Now we need to get all the extension methods:

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

Now, those defined directly in terms of string (SomeMethod(this string arg)) on a base class (SomeMethod(this object arg)) will be:

var stringExtensions = availableExtensionMethods
    .Where(info => info.FirstParam.ParameterType.IsAssignableFrom(typeof(string)))
    .Select(info => info.Method);

The above would include (this IEnumerable<char> arg). To get defined generically on a generic type string implements (e.g (this IEnumerable<T> arg) we would use:

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;

You can then Union these together to get the lot.

I haven't included checks on constraints here though.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • thank you very match, it's work. I can't evaluate your answer, because i have bad reputation. It's my first question and i have "-2", don't have any idea why, may be it's because i have a bad english :)) – itihonov Nov 13 '16 at 19:26
0

Extension methods of string are located in Enumerable class and IEnumerable interface which are in System.Linq namespace in mscorlib assembly. You can get the names of the extension methods in System.Linq in a manner like this:

    //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);
    }
αNerd
  • 528
  • 1
  • 6
  • 11