parent
2897acbea0
commit
614ad24b5c
2 changed files with 132 additions and 0 deletions
@ -0,0 +1,24 @@ |
||||
// Author: Gockner, Simon |
||||
// Created: 2020-11-13 |
||||
// Copyright(c) 2020 SimonG. All Rights Reserved. |
||||
|
||||
using System; |
||||
|
||||
namespace GBase.Exceptions |
||||
{ |
||||
/// <summary> |
||||
/// Could not find generic method |
||||
/// </summary> |
||||
internal class GenericMethodNotFoundException : Exception |
||||
{ |
||||
/// <summary> |
||||
/// Could not find generic method |
||||
/// </summary> |
||||
/// <param name="functionName">The name of the generic method</param> |
||||
public GenericMethodNotFoundException(string functionName) |
||||
: base($"Could not find function {functionName}") |
||||
{ |
||||
|
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,108 @@ |
||||
// Author: Gockner, Simon |
||||
// Created: 2020-11-13 |
||||
// Copyright(c) 2020 SimonG. All Rights Reserved. |
||||
|
||||
using System; |
||||
using System.Reflection; |
||||
using System.Threading.Tasks; |
||||
using GBase.Exceptions; |
||||
|
||||
namespace GBase.Helpers |
||||
{ |
||||
internal static class GenericMethodCaller |
||||
{ |
||||
/// <summary> |
||||
/// Call a generic method without generic type parameters |
||||
/// </summary> |
||||
/// <param name="caller">The caller of the method</param> |
||||
/// <param name="functionName">The name of the method to call</param> |
||||
/// <param name="bindingFlags">The <see cref="BindingFlags"/> to find the method</param> |
||||
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param> |
||||
/// <param name="parameters">The parameters of the method</param> |
||||
/// <returns>The result of invoking the method</returns> |
||||
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception> |
||||
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception> |
||||
public static object Call(object caller, string functionName, BindingFlags bindingFlags, Type genericParameter, params object[] parameters) => |
||||
GetGenericMethod(caller, functionName, bindingFlags, genericParameter).InvokeGenericMethod(caller, parameters); |
||||
|
||||
/// <summary> |
||||
/// Call a generic method without generic type parameters |
||||
/// </summary> |
||||
/// <param name="caller">The caller of the method</param> |
||||
/// <param name="functionName">The name of the method to call</param> |
||||
/// <param name="bindingFlags">The <see cref="BindingFlags"/> to find the method</param> |
||||
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param> |
||||
/// <param name="secondGenericParameter"></param> |
||||
/// <param name="parameters">The parameters of the method</param> |
||||
/// <returns>The result of invoking the method</returns> |
||||
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception> |
||||
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception> |
||||
public static object Call(object caller, string functionName, BindingFlags bindingFlags, Type genericParameter, Type secondGenericParameter,params object[] parameters) => |
||||
GetGenericMethod(caller, functionName, bindingFlags, genericParameter, secondGenericParameter).InvokeGenericMethod(caller, parameters); |
||||
|
||||
/// <summary> |
||||
/// Call a generic method asynchronously without generic type parameters |
||||
/// </summary> |
||||
/// <param name="caller">The caller of the method</param> |
||||
/// <param name="functionName">The name of the method to call</param> |
||||
/// <param name="bindingFlags">The <see cref="BindingFlags"/> to find the method</param> |
||||
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param> |
||||
/// <param name="parameters">The parameters of the method</param> |
||||
/// <returns>The result of invoking the method</returns> |
||||
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception> |
||||
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception> |
||||
public static async Task<object> CallAsync(object caller, string functionName, BindingFlags bindingFlags, Type genericParameter, params object[] parameters) => |
||||
await GetGenericMethod(caller, functionName, bindingFlags, genericParameter).InvokeGenericMethodAsync(caller, parameters); |
||||
|
||||
/// <summary> |
||||
/// Call a generic method asynchronously without generic type parameters |
||||
/// </summary> |
||||
/// <param name="caller">The caller of the method</param> |
||||
/// <param name="functionName">The name of the method to call</param> |
||||
/// <param name="bindingFlags">The <see cref="BindingFlags"/> to find the method</param> |
||||
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param> |
||||
/// <param name="secondGenericParameter"></param> |
||||
/// <param name="parameters">The parameters of the method</param> |
||||
/// <returns>The result of invoking the method</returns> |
||||
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception> |
||||
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception> |
||||
public static async Task<object> CallAsync(object caller, string functionName, BindingFlags bindingFlags, Type genericParameter, Type secondGenericParameter, params object[] parameters) => |
||||
await GetGenericMethod(caller, functionName, bindingFlags, genericParameter, secondGenericParameter).InvokeGenericMethodAsync(caller, parameters); |
||||
|
||||
private static MethodInfo GetGenericMethod(object caller, string functionName, BindingFlags bindingFlags, params Type[] genericParameters) |
||||
{ |
||||
MethodInfo genericMethod = caller.GetType().GetMethod(functionName, bindingFlags)?.MakeGenericMethod(genericParameters); |
||||
|
||||
if (genericMethod == null) |
||||
throw new GenericMethodNotFoundException(functionName); |
||||
|
||||
return genericMethod; |
||||
} |
||||
|
||||
private static object InvokeGenericMethod(this MethodInfo genericMethod, object caller, params object[] parameters) |
||||
{ |
||||
try //exceptions thrown by methods called with invoke are wrapped into another exception, the exception thrown by the invoked method can be returned by `Exception.GetBaseException()` |
||||
{ |
||||
return genericMethod.Invoke(caller, parameters); |
||||
} |
||||
catch (Exception ex) |
||||
{ |
||||
throw ex.GetBaseException(); |
||||
} |
||||
} |
||||
|
||||
private static async Task<object> InvokeGenericMethodAsync(this MethodInfo genericMethod, object caller, params object[] parameters) |
||||
{ |
||||
try //exceptions thrown by methods called with invoke are wrapped into another exception, the exception thrown by the invoked method can be returned by `Exception.GetBaseException()` |
||||
{ |
||||
dynamic awaitable = genericMethod.Invoke(caller, parameters); |
||||
await awaitable; |
||||
return awaitable.GetAwaiter().GetResult(); |
||||
} |
||||
catch (Exception ex) |
||||
{ |
||||
throw ex.GetBaseException(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue