Link to home
Start Free TrialLog in
Avatar of Grant Surridge
Grant SurridgeFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Csharp - Dynamically calling a void

Hi

Please forgive some of my .net terminology, hopefully this makes sense

I want to dynamically called a CSharp void (sub procedure etc etc), based on the value in a database

So for instance, lets say VariableA has a value of XYZ. I then want to look up the value of XYZ, and return the void that needs to be excuted, e.g Hello World

Then if ABC is the value, then it would return Goodbye World, and then execute that void

So essentially,execution of the void is all done from 1 line of code, but the void to actually be executed comes from a datanase

I hope that this makes sense. I am pretty sure it is possible, I just have no idea what its called to be able to start a google search

Thanks
Avatar of kaufmed
kaufmed
Flag of United States of America image

Here's one example:

using System;
using System.Collections.Generic;

namespace _27409039
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, Action> functionMap = new Dictionary<string, Action>();

            functionMap.Add("XYZ", HelloWorld);
            functionMap.Add("ABC", GoodbyeWorld);

            string dbValue = "XYZ";

            functionMap[dbValue]();

            dbValue = "ABC";

            functionMap[dbValue]();

            Console.ReadKey();
        }

        static void HelloWorld()
        {
            Console.WriteLine("Hello World!");
        }

        static void GoodbyeWorld()
        {
            Console.WriteLine("Goodbye World!");
        }
    }
}

Open in new window

Hello, I think he want something more like:
using System;

namespace Demo
{
    static class Program
    {
        static void Main(string[] args)
        {
            System.Type myType = typeof(Program);

            InvoqueMyMethod(myType, "XYZ");
            InvoqueMyMethod(myType, "ABC");

            Console.ReadKey();
        }

        static void InvoqueMyMethod(System.Type myType, string myMethodName)
        {
              myType.GetMethod(myMethodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static).Invoke(null, null);
         }

        static void HelloWorld()
        {
            Console.WriteLine("Hello World!");
        }

        static void GoodbyeWorld()
        {
            Console.WriteLine("Goodbye World!");
        }

    }
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Carlos Villegas
Carlos Villegas
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
..... I mean lines 11 and 12.....
If you know the function names ahead of time, why use reflection?
Maintenance, simplicity, I think. From the point of view of performance I prefer your example of course.
Avatar of Grant Surridge

ASKER

Hi

I'll have a play with these, thanks. How do you handle passing parameters too?

Does it just need to be a default of args[] or something ?

I'll let you know how I get on

Thanks
Hi

I think yv889c's method words best. The reason being that they names of the functions will also be stored in the database (i think) and so being able to provide the string name works best

However....

One issue I seem to have (what you provided works no problem by the way), is that, is there a limitation to the scope that it can "see" ?

I want to call a function that is in a different DLL file.

If in my code i call "HelloWorld" it will only work if it is within the same namespace. If it is in a different namespace, it returns an "object not set" error

Any thoughts ?

Thanks
Have managed to get it to work.

System.Type myType = typeof(Program); actually needs to be the namespace that the method is in (not sure how I can assign this dynamically at the moment, as it needs a proper type, i need to provide a string

Then within the invoke function, I put this, which seems to work

it doesn't have the binding info that was provided, am not sure what this does to be honest, so will start to read up !

Thanks

            MethodInfo m = myType.GetMethod(myMethodName);
            m.Invoke(null, null);
Hello, to pass parameters to your methods you can use something like this:
static void InvoqueMyMethod(System.Type myType, string myMethodName, params object[] parameters)
{
    myType.GetMethod(myMethodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static).Invoke(null, parameters);
}

Open in new window


Also, all these examples are based on static methods, if you are going to invoke instance methods the code must be slightly modified.


I have modified the example to show you how to get a Type by its full name, and passing parameters to a method too:
using System;

namespace Demo
{
    static class Program
    {
        static void Main()
        {
            // This get the current assembly that containt the methods that you want to invoke.
            // Also you can load externals assemblys.
            System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
            
            // To get the type that contain the methods that you want to invoke, you must use the full name of the type,
            // Demo is the namespace where is the Program class located, so Demo.Program.
            System.Type myType = myAssembly.GetType("Demo.Program");

            // This call the static method Program.HelloWorld, passing two parameters to it.
            InvoqueMyMethod(myType, "HelloWorld", "Hello!", 123);

            // This call the static method Program.GoodbyeWorld, without parameters.
            InvoqueMyMethod(myType, "GoodbyeWorld", null);
        }

        static void InvoqueMyMethod(System.Type myType, string myMethodName, params object[] parameters)
        {
            myType.GetMethod(myMethodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static).Invoke(null, parameters);
        }

        static void HelloWorld(string text, int number)
        {
            Console.WriteLine("Hello World! - " + text + " - " + number.ToString());
        }

        static void GoodbyeWorld()
        {
            Console.WriteLine("Goodbye World!");
        }
    }
}

Open in new window