Game Development Community

Go from String to Method

by Aaron Scovel · in Torque X 2D · 10/10/2010 (12:48 am) · 5 replies

I have a component that has a enum list of different methods that I want to call based on the selection.

How would I go about calling the method from a string state?

public enum sqwert_PieceType
        {
            Random,
            RedGem,
            GreenGem,
            BlueGem
        }

The methods look like this

public void BlueGem(bool animation)
        {
            _pieceValue = 20;
            // _soundfx = sound Effect name 
            if (animation)
            {
                _animUp = TorqueObjectDatabase.Instance.FindObject<T2DAnimationData>("");
                _animOver = TorqueObjectDatabase.Instance.FindObject<T2DAnimationData>("");
                _animPress = TorqueObjectDatabase.Instance.FindObject<T2DAnimationData>("");
            }
            else
            {
                _staticUp = TorqueObjectDatabase.Instance.FindObject<RenderMaterial>("BlueGemMaterial");
                _staticOver = TorqueObjectDatabase.Instance.FindObject<RenderMaterial>("BlueGemGlowMaterial");
                _staticPress = TorqueObjectDatabase.Instance.FindObject<RenderMaterial>("");
            }
        }

In short I need to call the methods like this

BlueGem(_enableAnimation);

The method to run will be different depending on the component selection
and would like to run the method by doing something like this. Obviously the below is wrong.

// _pieceType is the enum value (the method in string form)
     _pieceType.ToString()(_enableAnimation);


What do you think? Should I even go through the hassle of trying to do it this way or just setup a "switch/case" or "if" to check the _pieceType and then call the corresponding Method that way? Mainly I am trying to limit the size of code (should I even worry about this when coding in C#?).

About the author

Previously a PHP/MySQL Programmer/Web Developer of 10 years. In Aug 2010 I decided to change careers, and this is were I landed! I also parent 3 kids full time. TopNotched.com


#1
10/10/2010 (3:00 am)
I ended up going with a switch for now

switch (_pieceType.ToString())
                {
                    case "Random":
                        RandomGem(_enableAnimation);
                        break;
                    case "RedGem":
                        RedGem(_enableAnimation);
                        break;
                    case "GreenGem":
                        GreenGem(_enableAnimation);
                        break;
                    case "BlueGem":
                        BlueGem(_enableAnimation);
                        break;
                }

Not exactly what I was trying to achieve, but it works for now :-)

I would still like to "Go from String to Method" (within the same class) if anyone knows how I would do this. Thanks.
#2
10/10/2010 (7:19 am)
I can't really help with the method call right now, but I'm sure it's possible. First I would though use the enum better.. try it this way..

switch (_pieceType)  
                {  
                    case sqwert_PieceType.Random :  
                        RandomGem(_enableAnimation);  
                        break;  
                    case sqwert_PieceType.RedGem:  
                        RedGem(_enableAnimation);  
                        break;  
                    case sqwert_PieceType.GreenGem:  
                        GreenGem(_enableAnimation);  
                        break;  
                    case sqwert_PieceType.BlueGem:  
                        BlueGem(_enableAnimation);  
                        break;  
                }

This would make your logic easier to read, and faster.

#3
10/10/2010 (9:42 am)
You can use a Dictionary of delegates, perhaps something like this

namespace StarterGame2D
{
    public delegate void GemCommandDelegate(bool enableAnimation);
	
    public class GemCommand
    {
	public GemCommand()
	{
     	    _SetupGemDictionary()
	}
		
	public Dictionary<string, GemCommandDelegate> GemCommandDictionary
	{
	    get { return _gemCommandDictionary; }
	    set { _gemCommandDictionary = value; }
	}
	
	public static void RandomGem(bool enableAnimation)
	{
		// Random Gem stuff here...
	}

	public static void RedGem(bool enableAnimation)
	{
		// Red Gem stuff here...
	}
		
	public static void GreenGem(bool enableAnimation)
	{
		// Green Gem stuff here...
	}
		
	public static void BlueGem(bool enableAnimation)
	{
		// Blue Gem stuff here...
	}
		
	void _SetupGemDictionary()
	{
	    _gemCommandDictionary.Add("RandomGem", _randomGem);
	    _gemCommandDictionary.Add("RedGem", _redGem);
	    _gemCommandDictionary.Add("GreenGem", _greenGem);
	    _gemCommandDictionary.Add("BlueGem", _blueGem);
	}

        // Gem Commands
        private static GemCommandDelegate _randomGem = new GemCommandDelegate(RandomGem);
        private static GemCommandDelegate _redGem = new GemCommandDelegate(RedGem);
        private static GemCommandDelegate _greenGem = new GemCommandDelegate(GreenGem);
        private static GemCommandDelegate _blueGem = new GemCommandDelegate(BlueGem);

	private Dictionary<string, GemCommandDelegate> _gemCommandDictionary = new Dictionary<string, GemCommandDelegate>();
#4
10/10/2010 (11:11 am)
@Will: Thanks for the performance tip

@Alex: That looks like it would work too.

.. I am currently trying this ...

// Get the Method Name (newType)
            _methodString = ((sOptionRow)_options[_currentSelection]).newType; 
            // Define _piece with the Class
            sqwert_AllPieces _piece;
            // Get Method From Class with string value
            MethodInfo PieceData = typeof(sqwert_AllPieces).GetMethod(_methodString);
            // Run the Method
            PieceData.Invoke(_piece, _enableAnimation);

I cant get the above to work (I think the param for invoke needs to be in array form), but if I do the following
with a method that doesn't have parameters, it works

PieceData.Invoke(_piece, null);

#5
10/10/2010 (2:39 pm)
I suspect alex's method would execute faster and with less overhead - although you want to confirm that by running some performance tests on it (using 'reflection' to call methods is usually relatively slow). It also seems like a cleaner more maintainable approach.