Last active
March 29, 2019 06:23
-
-
Save imgen/902047a615ddc1c48a89bbe78b0f01f6 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
using System; | |
using System.Linq.Expressions; | |
using System.Reflection; | |
public static class ReflectionUtils | |
{ | |
public static MethodInfo GetMethod<TInput, TOutput>(Expression<Func<TInput, TOutput>> methodCallExpression) => GetMethodByLambdaExpression(methodCallExpression); | |
public static MethodInfo GetMethod<TInput>(Expression<Action<TInput>> methodCallExpression) => GetMethodByLambdaExpression(methodCallExpression); | |
public static MethodInfo GetMethod<TOutput>(Expression<Func<TOutput>> methodCallExpression) => GetMethodByLambdaExpression(methodCallExpression); | |
public static MethodInfo GetMethod(Expression<Action> methodCallExpression) => GetMethodByLambdaExpression(methodCallExpression); | |
/// <summary> | |
/// Get the method definition by a lambda expression instead of using reflection api | |
/// Very helpful when the generic method has a lot of overloads, especially helpful | |
/// if it's a generic overloaded method | |
/// </summary> | |
/// <param name="methodCallExpression">The lambda expression that invokes the desired method</param> | |
/// <returns>The method information</returns> | |
public static MethodInfo GetMethodByLambdaExpression(LambdaExpression methodCallExpression) | |
{ | |
var method = (methodCallExpression.Body as MethodCallExpression)?.Method ?? | |
throw new ArgumentException("The provided expression doesn't invoke a method as expected", | |
nameof(methodCallExpression)); | |
return method.IsConstructedGenericMethod ? method.GetGenericMethodDefinition() : method; | |
} | |
} |
This file contains hidden or 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
using System; | |
using Should; | |
using System.Linq; | |
using static ReflectionUtils; | |
private class Clazz | |
{ | |
public string Method() => throw new NotImplementedException(); | |
public void Method(string id) {} | |
public string Method(int id) => throw new NotImplementedException(); | |
public void Method<T>(IdGetter<T> idGetter) {} | |
public string Method<T>(Func<T> idGetter) => throw new NotImplementedException(); | |
} | |
private class IdGetter<T> | |
{ | |
public T GetId() => throw new NotImplementedException(); | |
} | |
var type = typeof(Clazz); | |
var klazz = new Clazz(); | |
var methodName = nameof(Clazz.Method); | |
var method = GetMethod(() => new Clazz().Method()); | |
var expectedMethod = type.GetMethod(methodName, new Type[]{}); | |
method.ShouldEqual(expectedMethod); | |
var method2 = GetMethod((Clazz clazz) => clazz.Method()); | |
method2.ShouldEqual(method); | |
var method3 = GetMethod((Clazz clazz) => clazz.Method("str")); | |
var expectedMethod3 = type.GetMethod(methodName, new []{typeof(string)}); | |
method3.ShouldEqual(expectedMethod3); | |
var method4 = GetMethod(() => klazz.Method(new IdGetter<int>())); | |
var expectedMethod4 = type.GetMethods() | |
.SingleOrDefault(x => x.ContainsGenericParameters && | |
x.GetParameters().SingleOrDefault()?.ParameterType.GetGenericTypeDefinition() == typeof(IdGetter<>)); | |
method4.ShouldEqual(expectedMethod4); | |
var method5 = GetMethod(() => klazz.Method(() => true)); | |
var expectedMethod5 = type.GetMethods() | |
.SingleOrDefault(x => x.ContainsGenericParameters && | |
x.GetParameters().SingleOrDefault()?.ParameterType.GetGenericTypeDefinition() == typeof(Func<>)); | |
method5.ShouldEqual(expectedMethod5); | |
// If we don't invoke method in the lambda expression, should throw ArgumentException | |
Assert.Throws<ArgumentException>(() => GetMethod(() => klazz == null)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment