Created
February 21, 2017 21:58
-
-
Save shanecelis/a0fca4fdf489e808c98057b49ec003c1 to your computer and use it in GitHub Desktop.
Search for a method based on generic arguments in addition to name and parameters.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Search for a method based on generic arguments in addition to name and | |
parameters. Most useful for disambiguating methods with the same name. | |
If the elements of genericArgs are not null, it will return the specialized | |
generic method. Otherwise it will return the generic method definition. | |
Finally, if genericArgs has no elements, it will return a non-generic | |
method. If no method is found, it will return null. | |
e.g. Suppose I had the following methods in a class Minibuffer: | |
IPromise<string> Read(Prompt p) { ... } | |
IPromise<T> Read<T>(Prompt p) { ... } | |
And I wanted to get the generic one: | |
Minibuffer.GetMethodGeneric("Read", new [] {typeof(int)}, new [] {typeof(Prompt)}) -> | |
IPromise`1 Read[Int64](seawisphunter.minibuffer.Prompt) | |
Minibuffer.GetMethodGeneric("Read", new Type[] {null}, new [] {typeof(Prompt)}) -> | |
IPromise`1 Read[T](seawisphunter.minibuffer.Prompt) | |
Or I could get the non-generic one: | |
Minibuffer.GetMethodGeneric("Read", new Type[] {}, new [] {typeof(Prompt)}) -> | |
IPromise`1 Read(seawisphunter.minibuffer.Prompt) | |
*/ | |
// http://stackoverflow.com/questions/5218395/reflection-how-to-get-a-generic-method | |
public static MethodInfo GetMethodGeneric(this Type t, | |
string name, | |
Type[] genericArgs, | |
Type[] parameterTypes) { | |
var myMethod | |
= t | |
.GetMethods() | |
// I can count the number of times I've had to actually XOR on one hand. | |
.Where(m => (genericArgs.Length == 0 ^ m.IsGenericMethod) | |
&& m.Name == name) | |
.Where(m => | |
{ | |
var paramTypes = m.GetParameters(); | |
var genParams = m.GetGenericArguments(); | |
return genParams.Length == genericArgs.Length | |
&& Enumerable.SequenceEqual(paramTypes.Select(p => p.ParameterType), | |
parameterTypes); | |
}) | |
.SingleOrDefault(); | |
if (myMethod != null | |
&& myMethod.ContainsGenericParameters | |
&& genericArgs.All(p => p != null)) { | |
return myMethod.MakeGenericMethod(genericArgs); | |
} | |
return myMethod; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment