My goal was to use a string to execute a method of a class, without having to use a comparison for each possible string value. The benefits to this are flexibility, and ease of scalability and maintenance.
If, for example, we're defining a menu system via XML, we can use a string to specify the name of a function to execute when a menu item is selected. Using reflection, we can avoid having to use a switch statement with a case for each possible menu selection; all we'll have to do is make sure an appropriate function exists, and add the name of that function as a textual property of a menu item element within our XML document.
Here is my test case for invoking a method with a string, in the form of a C# Console application.
using System;
using System.Reflection;
/*
*
* A simple demonstration of using reflection to invoke a method of an object
* using a string whose value matches the name of said method, without using
* explicit comparisons such as a case statement. (Breeeeathe!)
*
*/
/*
*
* Written by Adam Richards
* www.failcode.com
*
* Copyright 2008 Adam Richards
*
* TERMS OF USE:
* - Use at will
* - Use at your own risk
* - Please give me credit when used in a similar context
*
*/
namespace ReflectionTest1
{
// A class that provides some simple methods we'll be using soon...
public class TestClass
{
public void help()
{
Console.Write("You can execute a function by typing its name.\n\n");
Console.Write("Available function names are:\n help\n test1\n test2\n quit\n\n");
}
public void test1()
{
Console.Write("Hey cool, you executed function test1!\n\n");
}
public void test2()
{
Console.Write("Woot, function test2 got executed!\n\n");
}
public void quit()
{
Console.Write("Goodbye!\n\n");
Program.timeToQuit = true;
}
}
class Program
{
// A static quit flag--static so we can modify it from TestClass.quit()
public static bool timeToQuit = false;
static void Main(string[] args)
{
// Instantiate our test class
TestClass testClass = new TestClass();
// A string that we'll use to catch the users input, and to run any functions who share
// a name with this string's value. We'll start with the help function, so the user
// has a clue on what to do.
string funcName = "help";
while (true)
{
// Build our binding flags here to keep our reflection invocation clean
BindingFlags bindingFlags =
BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.InvokeMethod;
try
{
// And here is the reflection magic:
typeof(TestClass).InvokeMember(
funcName, // The string that holds the name of the function
bindingFlags, // The binding flags we built above...
null, // No binder needed since our func's aren't overloaded
testClass, // The instance of our class to call the method of
null); // No arguments need to be passed to our functions
}
catch (Exception ex)
{
// NOTE: Here we compare the exception type to see if the string did not
// match the name of a function. If it didn't, we'll alert the user
// of the situation. Otherwise, it's a different error, which I've
// not explicitly prepared for :) In this case, the only error that
// will throw this exception is the function not existing. In other
// cases, this exception can mean other things. Rework this for
// mission critical applications!
if (ex.GetType() == typeof(MissingMethodException))
Console.Write("Sorry, you have typed a function name that does not exist.\n\n");
else
Console.Write("\n\nAn \"unhandled\" error has occurred...\n\n");
}
// Check our quit flag, and return from Main() if it's been set to true
if (timeToQuit) return;
// If we're still here, read the next line of input from the user
funcName = Console.ReadLine();
}
}
}
}
Download project (Visual C# 2008)
MSDN Page on Reflection

No comments:
Post a Comment