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 :)
Anonymous types typically are used in the select clause of a query expression to return a subset of the properties from each object in the source sequence. For more information about queries, see LINQ in C#. Anonymous types contain one or more public read-only properties.
In some cases, you might want to project a query to a new type, but the query would be your only use for the new type. Rather than create the type, you can project to an anonymous type.
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);
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With