简体   繁体   English

c#执行一个字符串作为代码

[英]c# execute a string as code

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# 这是我想要做的,我知道它可以用perl,php,python和java,但我正在使用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. 我想将functionName传递给方法,我希望它如上所述执行。

How this can be done? 怎么做到这一点?

Do i need ANTLR or any other tool for this? 我需要ANTLR或任何其他工具吗?

Thanks. 谢谢。

You can execute a method by name via Reflection. 您可以通过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: MethodInfo.Invoke会直接将方法的返回值作为Object返回,因此,例如,如果您返回一个字符串,则可以执行以下操作:

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.
}

Executing a string as if it were code is possible in c#, but it's not pretty or simple. 在c#中执行一个字符串就好像它是代码一样,但它并不漂亮或简单。 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. 现在,在您的情况下,您想要调用Web服务。 Since that ultimately comes down to xml anyway you have a couple options: 因为最终归结为xml,你有几个选择:

  • 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. 绕过内置系统以调用Web服务,并使用正确的名称在xml中的正确位置创建自己的Web请求。
  • 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 ? 你是说AVeryLargeWebServiceWithLotsOfMethodsToCall是你想要调用一个名为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 ? 或者AVeryLargeWebServiceWithLotsOfMethodsToCall是一个要调用名为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. 或者,您可以使用Action或其他一些委托来传递对要调用的函数的引用。

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

Why don't you just use .NET Remoting? 你为什么不使用.NET Remoting? It is made for exactly that. 它正是为此而制造的。

A completely other solution would be to use the CSharpCodeCompiler class. 一个完全不同的解决方案是使用CSharpCodeCompiler类。

Here are a couple utility methods which can handle class and instance method calls passed in as strings, with optional args and varargs. 下面是一些实用程序方法,它们可以处理作为字符串传递的类和实例方法调用,以及可选的args和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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM