Created
April 1, 2019 10:04
-
-
Save Tewr/e6aec3e7b430ee34f28d02d759de39ff to your computer and use it in GitHub Desktop.
Reflection-based console app to call and debug simple task-based api's
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 Newtonsoft.Json; | |
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
using System.Linq; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace Good_Gaz.Services.SirsConsoleClient | |
{ | |
partial class Program | |
{ | |
static partial void Wain(IEnumerable<string> args) { | |
var targetApi = GetTargetApiInstance(); | |
var targetApiType = targetApi.GetType(); | |
var availableMethods = targetApiType.GetMethods(); | |
var argsList = args.ToList(); | |
var method = argsList.FirstOrDefault(); | |
if (string.IsNullOrWhiteSpace(method)) | |
{ | |
OnHelpFlagged(targetApiType); | |
return; | |
} | |
argsList = argsList.Skip(1).ToList(); | |
var methodInfo = availableMethods.FirstOrDefault(x => x.Name.Equals(method, StringComparison.OrdinalIgnoreCase)); | |
if (methodInfo == null) | |
{ | |
OnHelpFlagged(targetApiType); | |
return; | |
} | |
var ct = CancellationToken.None; | |
var parameterInfos = methodInfo.GetParameters().Where(x => x.ParameterType != typeof(CancellationToken)).ToList(); | |
var types = parameterInfos.Select(x => x.ParameterType).ToArray(); | |
var typedArgsList = new List<object>(); | |
var ix = 0; | |
if (argsList.Count != types.Length) | |
{ | |
throw new ArgumentException($"Method '{methodInfo.Name}' expects the following arguments: {string.Join(", ", parameterInfos.Select(pi => $"{pi.ParameterType} {pi.Name}")) }"); | |
} | |
var resultProperty = typeof(Task<>).MakeGenericType(methodInfo.ReturnType.GetGenericArguments().FirstOrDefault()) | |
.GetProperty(nameof(Task<object>.Result)); | |
foreach (var strArg in argsList) | |
{ | |
var targetType = types[ix]; | |
try | |
{ | |
var typeConverter = TypeDescriptor.GetConverter(targetType); | |
typedArgsList.Add(typeConverter.ConvertTo(strArg, targetType)); | |
} | |
catch (Exception) | |
{ | |
Console.Error.WriteLine($"Unable to cast parameter '{strArg}' to {targetType.Name}"); | |
throw; | |
} | |
ix++; | |
} | |
typedArgsList.Add(ct); | |
var result = methodInfo.Invoke(targetApi, typedArgsList.ToArray()); | |
if (methodInfo.ReturnType == typeof(void)) | |
{ | |
return; | |
} | |
if (result is Task taskResult) | |
{ | |
taskResult?.Wait(); | |
if (methodInfo.ReturnType == typeof(Task)) | |
{ | |
return; | |
} | |
// unwrap task | |
result = resultProperty?.GetValue(taskResult); | |
} | |
if (result == null) | |
{ | |
Console.WriteLine("(null)"); | |
} | |
else | |
{ | |
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented)); | |
} | |
} | |
private static object GetTargetApiInstance() | |
{ | |
var injector = new List<object>(); | |
GetTargetApi(injector); | |
var targetApi = injector.FirstOrDefault(); | |
return targetApi; | |
} | |
static partial void OnHelpFlagged() | |
{ | |
OnHelpFlagged(GetTargetApiInstance().GetType()); | |
} | |
static void OnHelpFlagged(Type targetType) | |
{ | |
Console.Error.WriteLine($"Usage: {System.Reflection.Assembly.GetExecutingAssembly().GetName()} [-h|-v|-d] <{string.Join("|", targetType.GetMethods().Select(x => x.Name))}> [method parameters]"); | |
} | |
static partial void OnVerboseFlagged() | |
{ | |
IsVerbose = true; | |
} | |
public static bool IsVerbose { get; set; } | |
/// <summary> | |
/// Add the target api as the first member of the list. | |
/// </summary> | |
/// <param name="injectorList"></param> | |
static partial void GetTargetApi(List<object> injectorList); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment