views:

81

answers:

3

What Linq expression would I use to select the 1rst overloaded method that accepts a single string parameter?

For example to return the DateTime.ToString(string format) instead of the DateTime.ToString(IFormatProvider provider).

t = typeof(DateTime);
string[] validMethods = { "ToString" };
return t.GetMethods().Where(a => validMethods.Contains(a.Name) & a.GetParameters().Length == 1).ToArray();
+3  A: 

Something like this:

var match = (from method in type.GetMethods()
             where validMethods.Contains(method.Name)
             let parameters = method.GetParameters()
             where parameters.Length == 1
             where parameters[0].ParameterType == typeof(string)
             select method).FirstOrDefault();

if (match != null)
{
    ...
}

Normally there couldn't be more than one method with a single string parameter, but it can happen, if you're looking at a derived class which hides a base class method with exactly the right parameter list and name. At that point I don't think it's specified which method you'll get first though...

Jon Skeet
+8  A: 

You can check the whole parameter list with a SequenceEqual call:

t = typeof(DateTime);
string[] validMethods = { "ToString" };
Type[] parameters = { typeof(string) };
return t.GetMethods()
        .Where(a => validMethods.Contains(a.Name) &&
                    a.GetParameters().Select(p => p.ParameterType)
                                     .SequenceEqual(parameters)).ToArray();
Mehrdad Afshari
I like it - that scales up very nicely to more parameter types to check.
Jon Skeet
Thank you, I can see how this would allow other sequences of parameters.
QSmienk
A: 

I would have added this as a comment to Mehrdad's excellent answer, but don't think it would have formatted correctly...

Looking at deeply nested LINQ expressions makes my brain hurt (probably because I'm a LINQ newbie).

Here's my attempt to reformat it in a more readable way.

     var t = typeof(DateTime);
     string[] validMethods = { "ToString" };
     var parameters = new[] { typeof(string) };

     return t.GetMethods()
             .Where
             (
                a => validMethods.Contains(a.Name)
                     && 
                     a.GetParameters()
                      .Select(p => p.ParameterType)
                      .SequenceEqual(parameters)
             )
             .ToArray();

Still makes my brain hurt - but not quite as much.

Tom Bushell