Pergunta

I'm making a query on a MethodInfo[] where I'm trying to find all the methods that have a return type of void, and has only one parameter of a certain type. I want to do it in the most minimalistic and shortest way.

One way to do it would be:

var validMethods = methods.Where(m => m.ReturnType == typeof(void) && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == wantedType);

or

var validMethods = methods
      .Where(m => m.ReturnType == typeof(void))
      .Where(m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == wantedType);

But there's a redundant GetParameters call - One call should be enough. So I thought I could cache that to an anonymous type like so:

var validMethods = methods
    .Where(m => m.ReturnType == typeof(void))
    .Select(m => new { Params = m.GetParameters() })
    .Where(p => p.Length == 1 && p[0].ParameterType == transition.eventType);

But it didn't work, I got errors saying there's no Length nor an indexer for the anonymous type p which is of type ParameterInfo[]

Is this the shortest way of writing this query? if so, how can I get the anonymous type to work? if not, what's the shortest way of doing this? (get all methods of void return, and of one param where that param is of a certain type)

Thanks for any help :)

Foi útil?

Solução

With query syntax you can introduce new range variable which will hold method parameters

from m methods.Where(m => m.ReturnType == typeof(void))
let p = m.GetParameters()
where p.Length == 1 && p[0].ParameterType == wantedType
select m

Method syntax is not that beautiful:

methods.Where(m => m.ReturnType == typeof(void))
       .Select(m => new { m, p = m.GetParameters() })
       .Where(x => x.p.Length == 1 && x.p[0].ParameterType == wantedType)
       .Select(x => x.m);

Outras dicas

I agree with Sergey Berezovskiy that the method syntax he showed is less beautifull than the query syntax. But the method syntax can be rewritten to this:

methods.Where(IsTheRightMethod);

and a regular method:

private bool IsTheRightMethod(MethodInfo methodInfo)
{
    if (methodInfo.ReturnType != typeof(void)) return false;
    var parameters = methodInfo.GetParameters();
    return parameters.Length == 1 && parameters[0].ParameterType == typeof(wantedType);
}

The OP wanted a short solution. If this is short depends on how you look at it. The Linq query is shorter and anonymous types are not created.

This solution also makes debugging easier and is also easier to extend. An example of the latter might be:

methods.Where(m => IsTheRightMethod(m, typeof(wantedType), 1));

and

private bool IsTheRightMethod(MethodInfo methodInfo, Type parametertype, int parametersLenght)
{
    if (methodInfo.ReturnType != typeof(void)) return false;
    var parameters = methodInfo.GetParameters();
    return parameters.Length == parametersLenght && 
           parameters.All(p => p.ParameterType == parametertype);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top