Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all methods on an Type[] of interfaces using LINQ?

Tags:

c#

linq

I'm trying to find all the methods that an interface grants me through reflection. I have a type array which I verify has only interfaces, from there I need to extract all the methods.Unfortunately, If I do something like typeof(IList).GetMethods() it only returns the methods on IList not those on ICollection, or IEnumerable I've tried the following linq query but it doesn't return the methods found on the outer interfaces. How can I fix my query?

from outerInterfaces in interfaces
from i in outerInterfaces.GetInterfaces()   
from m in i.GetMethods()
select m

If this was SQL I could do something like a recursive CTE with a union all, but I don't think such a syntax exist in C#. Can anyone help here?

like image 741
Michael B Avatar asked Nov 18 '10 16:11

Michael B


2 Answers

How about something like this:

 typeof(IList<>).GetMethods().Concat(typeof(IList<>)
                .GetInterfaces()
                .SelectMany(i => i.GetMethods()))
                .Select(m => m.Name)
                .ToList().ForEach(Console.WriteLine);

EDIT: Response to the comments.

Tested it with this code:

    public interface IFirst
    {
        void First();
    }

    public interface ISecond : IFirst
    {
        void Second();
    }

    public interface IThird :ISecond
    {
        void Third();
    }

    public interface IFourth : IThird
    {
        void Fourth();
    }

Test code:

        typeof(IFourth).GetMethods().Concat(typeof(IFourth)
            .GetInterfaces()
            .SelectMany(i => i.GetMethods()))
            .Select(m => m.Name)
            .ToList().ForEach(Console.WriteLine);

And the output is:

Fourth
Third
Second
First
like image 60
BFree Avatar answered Oct 08 '22 08:10

BFree


There's no "built-in" LINQ recursion (that I'm aware of), but you can create a boilerplate LINQ extension to get all descendants: (warning: compiled in notepad)

static public class RecursionExtensions
{
    static public IEnumerable<T> AllDescendants<T>(this IEnumerable<T> source, 
                                                Func<T, IEnumerable<T>> descender)
    {
        foreach (T value in source)
        {
            yield return value;

            foreach (T child in descender(value).AllDescendants<T>(descender))
            {
                yield return child;
            }
        }
    }
}

Then you can use it like this, treating the base types a descendant nodes in a tree:

  from ifaceType in interfaces.AllDescendants( t => t.GetInterfaces())

Given that you can compose your method selector:

from ifaceType in interfaces.AllDescendants( t=> t.GetInterfaces())
from m in ifaceType.GetMethods()
select m

which should give you all methods in all interfaces in the interfaces collection, plus all base interfaces

like image 22
Philip Rieck Avatar answered Oct 08 '22 08:10

Philip Rieck