- Home /
How can I use something like Invoke() to call a method in another class?
I'm making a developer console, in it I can call a local function via Invoke(nameOfFunction) with the user submitting the string nameOfFunction to the developer console. I want to know of a way to do this so that I can call not only local functions but also external functions. Currently, if I try to do so by typing in the console: "ExternalClass.TestMethod" It tries to call DebugConsole.ExternalClass.TestMethod()
How can I make it work with other classes?
Any help is much appreciated :)
Answer by SolidAlloy · Sep 02, 2020 at 04:38 PM
MonoBehaviour's Invoke method cannot be used in such a way because it requires a class instance, so Reflection is the way to go. I suppose you wouldn't want to write the full assembly-qualified class type in the console, so I found a method to find the class type by its short name and slightly modified it.
Here is the solution. It allows to invoke only static methods with no parameters. You can modify the method to take a variable number of parameters but it depends on your implementation of the developer console. If you would like to invoke instance methods as well, you need to decide how to find the class instances or create new instances.
private void InvokeMethodAtPath(string methodPath)
{
if ( ! methodPath.Contains('.'))
{
Invoke(methodPath, 0f);
return;
}
var classAndMethod = methodPath.Split('.');
if (classAndMethod.Length != 2)
{
Debug.Log("Path can contain only one class name and method, separated by dot.");
return;
}
string className = classAndMethod[0];
string methodName = classAndMethod[1];
var classTypes = GetTypesByName(className);
if (classTypes.Count != 1)
{
Debug.Log($"Expected to find one type by name '{className}', found {classTypes.Count}");
return;
}
Type classType = classTypes[0];
BindingFlags filter = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
var methodInfo = classType.GetMethod(methodName, filter);
if (methodInfo == null)
{
Debug.Log("Method does not exist");
}
else
{
// Only static methods with no parameters are supported.
methodInfo.Invoke(null, null);
}
}
/// <summary>
/// Gets all Type instances matching the specified type name with just non-namespace qualified class name.
/// </summary>
/// <param name="typeName">Name of the class sought.</param>
/// <returns>Types that have the class name specified. They may not be in the same namespace.</returns>
private static List<Type> GetTypesByName(string typeName)
{
var returnVal = new List<Type>();
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
var assemblyTypes = a.GetTypes();
returnVal.AddRange(assemblyTypes.Where(type => type.Name == typeName));
}
return returnVal;
}
You can use the method the following way:
InvokeMethodAtPath("ExternalClass.TestMethod");