Created
April 27, 2024 20:12
-
-
Save muhammetozeski/651ce2c963989fc301488131d21fb676 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.Reflection; | |
/// <summary> | |
/// This class is for calling a function from a class with string inputs. Example usage: | |
///<code> | |
///Console.WriteLine("You can call these functions:"); | |
///string[] functions = CallFunctions.GetMethodsAsStrings(typeof(TestClass)); | |
///for (int i = 0; i < functions.Length; i++) Console.WriteLine(functions[i]); | |
///Console.WriteLine("Write command:"); | |
///string input = Console.ReadLine(); | |
///bool result = CallFunctions.Call(typeof(TestClass), input); | |
///if (result) p("method is called succesfully"); | |
///else p("method couldn't be called"); | |
///</code> | |
/// </summary> | |
public static class CallFunctions | |
{ | |
public static bool PrintDebugMessages = true; | |
static void DefaultDebugPrintFunction(object message) | |
{ | |
if (!PrintDebugMessages) | |
return; | |
if (message == null) | |
{ | |
Console.WriteLine("null"); | |
return; | |
} | |
Console.WriteLine(message.ToString()); | |
} | |
/// <summary> | |
/// default print function for this class. it prints using Console.WriteLine() | |
/// you can change it if you are using a different platform such as unity. for example change it to MonoBehavior.Print function if you are working in unity. | |
/// </summary> | |
public static Action<object> DebugPrint = DefaultDebugPrintFunction; | |
/// <summary> | |
/// gets the methods with their parameters. only the methods will be returned that matches with this call:<br></br> type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); | |
/// </summary> | |
/// <param name="type">The class that will be scanned</param> | |
/// <returns></returns> | |
public static string[] GetMethodsAsStrings(Type type) | |
{ | |
MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); | |
List<string> MethodsAsStrings = new(); | |
foreach (MethodInfo method in methods) | |
{ | |
ParameterInfo[] parameters = method.GetParameters(); | |
string methodSignature = method.Name + "("; | |
for (int i = 0; i < parameters.Length; i++) | |
{ | |
string paramName = parameters[i].Name; | |
string paramType = parameters[i].ParameterType.Name; | |
string defaultValue = parameters[i].HasDefaultValue ? " = " + parameters[i].DefaultValue : ""; | |
methodSignature += paramType + " " + paramName + defaultValue; | |
if (i < parameters.Length - 1) | |
{ | |
methodSignature += ", "; | |
} | |
} | |
methodSignature += ")"; | |
MethodsAsStrings.Add(methodSignature); | |
} | |
return MethodsAsStrings.ToArray(); | |
} | |
/// <summary> | |
/// You can call only "public static" functions | |
/// </summary> | |
/// <param name="type">The class to be called its function</param> | |
/// <param name="Input">the calling input. Example: MyFunction(5,\"MyString\",4.8)</param> | |
public static bool Call(Type type, string Input) | |
{ | |
ParseInput(Input, out string methodName, out List<string> parameters); | |
MethodInfo[] methods = FindMethods(methodName, type.GetMethods()); | |
DebugPrint(methods.Length + " functions found"); | |
foreach (var method in methods) | |
{ | |
object[]? convertedParameters = ConvertParameters(parameters, method); | |
if (convertedParameters == null) | |
{ | |
DebugPrint("parameters don't match. Trying another method"); | |
continue; | |
} | |
try | |
{ | |
DebugPrint("method has been calling"); | |
for (int i = 0; i < convertedParameters.Length; i++) | |
{ | |
if(convertedParameters[i] != null) | |
DebugPrint("parameter " + i + " is " + convertedParameters[i].GetType().Name + " and its value is " + convertedParameters[i].ToString()); | |
} | |
method.Invoke(null, convertedParameters); | |
return true; | |
} | |
catch (Exception) | |
{ | |
return false; | |
throw; | |
} | |
} | |
return false; | |
} | |
static void ParseInput(string input, out string methodName, out List<string> parameters) | |
{ | |
try | |
{ | |
methodName = input.Substring(0, input.IndexOf("(")); | |
string paramString = input.Substring(input.IndexOf("(") + 1, input.LastIndexOf(")") - input.IndexOf("(") - 1); | |
parameters = new List<string>(paramString.Split(',')); | |
if (parameters.Count == 1 && parameters[0] == "") | |
parameters.Clear();//input is null but paramString.Split doesn't convert null. so you should make the list empty. | |
} | |
catch (Exception e) | |
{ | |
DebugPrint("An exception occured while parsing. Exception message: " + e.Message); | |
throw; | |
} | |
} | |
static MethodInfo[] FindMethods(string methodName, MethodInfo[] methods) | |
{ | |
return methods.Where(m => m.Name == methodName).ToArray(); | |
} | |
static object?[]? ConvertParameters(List<string> parameters, MethodInfo method) | |
{ | |
DebugPrint("Entered parameters:"); | |
foreach (var parameter in parameters) | |
{ | |
DebugPrint(parameter); | |
} | |
ParameterInfo[] methodParams = method.GetParameters(); | |
//if methodParams.Length less than parameters.Count then the function should be called is not this function. It should be another overload. | |
if (methodParams.Length < parameters.Count) | |
return null; | |
List<object?> convertedParams = new(); | |
for (int i = 0; i < methodParams.Length; i++) | |
{ | |
Type paramType = methodParams[i].ParameterType; | |
try | |
{ | |
if (i >= parameters.Count) | |
if (methodParams[i].HasDefaultValue) | |
convertedParams.Add(methodParams[i].DefaultValue); | |
else | |
return convertedParams.ToArray(); | |
else | |
{ | |
//if it's string, then return the string without quotes | |
if (parameters[i].StartsWith("\"") && parameters[i].EndsWith("\"") && paramType == typeof(string)) | |
convertedParams.Add(parameters[i].Substring(1, parameters[i].Length - 2)); | |
else | |
convertedParams.Add(Convert.ChangeType(parameters[i], paramType)); | |
} | |
} | |
catch (Exception ex) | |
{ | |
DebugPrint("Parameter converting error: " + ex.Message); | |
DebugPrint("type: " + paramType.Name); | |
return null; | |
} | |
} | |
return convertedParams.ToArray(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can simply create a console command program with this. Call your functions from console without needing any customisation for every function.