Question

Here is what i want to do, and i know it is possible with perl, php, python and java, but i am working with c#

how can i do the following:

public void amethod(string functionName)
{
    AVeryLargeWebServiceWithLotsOfMethodsToCall.getFunctionName();
}

I want to pass the functionName to the method and I want it to be executed as above.

How this can be done?

Do i need ANTLR or any other tool for this?

Thanks.

Was it helpful?

Solution

You can execute a method by name via Reflection. You need to know the type, as well as the method name (which can be the current object's type, or a method on a different object, or a static type). It looks like you want something like:

public void amethod(string functionName) 
{
    Type type = typeof(AVeryLargeWebServiceWithLotsOfMethodsToCall);
    MethodInfo method = type.GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
    method.Invoke(null,null); // Static methods, with no parameters
}

Edit in response to comment:

It sounds like you actually want to get a result back from this method. If that's the case, given that it's still a static method on the service (which is my guess, given what you wrote), you can do this. MethodInfo.Invoke will return the method's return value as an Object directly, so, if, for example, you were returning a string, you could do:

public string amethod(string functionName) 
{
    Type type = typeof(AVeryLargeWebServiceWithLotsOfMethodsToCall);
    MethodInfo method = type.GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
    object result = method.Invoke(null,null); // Static methods, with no parameters
    if (result == null)
        return string.Empty;
    return result.ToString();
    // Could also be return (int)result;, if it was an integer (boxed to an object), etc.
}

OTHER TIPS

Executing a string as if it were code is possible in c#, but it's not pretty or simple. It's also considered poor practice and insecure (you probably should avoid it in dynamic languages, too).

Instead, do something like this:

public void amethod(Action actionParam)
{
    actionParam();
}

Now, in your case you want to call a web service. Since that ultimately comes down to xml anyway you have a couple options:

  • Bypass the built-in system for calling web services and create your own web request with the correct name in the correct place in the xml.
  • Create delegates for each of the methods in the service to pass around, possibly via reflection.

Are you saying that AVeryLargeWebServiceWithLotsOfMethodsToCall is an instance of an object on which you want to invoke a method named functionName? If so:

MethodInfo method = AVeryLargeWebServiceWithLotsOfMethodsToCall.GetType().GetMethod(functionName);
method.Invoke(AVeryLargerWebServiceWithLotsOfMethodsToCall, null);

Or is AVeryLargeWebServiceWithLotsOfMethodsToCall a type on which you want to invoke a static method named functionName? If so:

MethodInfo method = typeof(AVeryLargeWebServiceWithLotsOfMethodsToCall).GetMethod(functionName);
method.Invoke(null, null);

It can be done using reflection. However, I believe you need an object reference to go with it.

Example from here

Type t = this.GetType();
MethodInfo method = t.GetMethod("showMessage");
method.Invoke(this, null);

Alternatively, you could use an Action or some other delegate to pass a reference to the function you want to call.

public void amethod(Action function)
{
    function();
}

Why don't you just use .NET Remoting? It is made for exactly that.

A completely other solution would be to use the CSharpCodeCompiler class.

Here are a couple utility methods which can handle class and instance method calls passed in as strings, with optional args and varargs.

This is NOT production code. It seems to work, at least with these trivial examples.

class Program
{
    static void Main(string[] args)
    {
        double alpha = Math.Sin(1.0);
        int beta = alpha.CompareTo(1.0);
        Console.WriteLine("{0} {1}", alpha, beta);

        double gamma = (double)CallClassMethod("System.Math.Sin", 1.0);
        int delta = (int)CallInstanceMethod(gamma, "CompareTo", 1.0);
        Console.WriteLine("{0} {1}", gamma, delta);

        string a = "abc";
        string x = "xyz";
        string r = String.Join(",", a, x);
        string s = r.Replace(",", ";");
        Console.WriteLine("{0} {1}", r, s);
        string t = (string)CallClassMethod("System.String.Join", ",", new String[] { a, x }); // Join takes varargs
        string u = (string)CallInstanceMethod(t, "Replace", ",", ";");
        Console.WriteLine("{0} {1}", t, u);
        Console.ReadKey();
    }

    static object CallClassMethod(string command, params object[] args)
    {
        Regex regex = new Regex(@"(.*)\.(\w*)");
        Match match = regex.Match(command);
        string className = match.Groups[1].Value;
        string methodName = match.Groups[2].Value;
        Type type = Type.GetType(className);
        List<Type> argTypeList = new List<Type>();
        foreach (object arg in args) { argTypeList.Add(arg.GetType()); }
        Type[] argTypes = argTypeList.ToArray();
        MethodInfo method = type.GetMethod(methodName, argTypes, null);
        return method.Invoke(null, args);
    }

    static object CallInstanceMethod(object instance, string methodName, params object[] args)
    {
        Type type = instance.GetType();
        List<Type> argTypeList = new List<Type>();
        foreach (object arg in args) { argTypeList.Add(arg.GetType()); }
        Type[] argTypes = argTypeList.ToArray();
        MethodInfo method = type.GetMethod(methodName, argTypes, null);
        return method.Invoke(instance, args);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top