当前位置:  开发笔记 > 编程语言 > 正文

从c#中的字符串创建匿名方法

如何解决《从c#中的字符串创建匿名方法》经验,为你挑选了3个好方法。

是否可以从字符串中创建c#中的匿名方法?

例如,如果我有一个字符串"x + y * z",才有可能把它变成某种方法/λ对象,我可以任意拨打x,y,z参数?



1> jason..:

这是可能的,是的.您必须解析字符串,例如,使用表达式树编译委托.

这是(x, y, z) => x + y * z使用表达式树创建的示例:

ParameterExpression parameterX = Expression.Parameter(typeof(int), "x");
ParameterExpression parameterY = Expression.Parameter(typeof(int), "y");
ParameterExpression parameterZ = Expression.Parameter(typeof(int), "z");
Expression multiplyYZ = Expression.Multiply(parameterY, parameterZ);
Expression addXMultiplyYZ = Expression.Add(parameterX, multiplyYZ);
Func f = Expression.Lambda>
(
    addXMultiplyYZ,
    parameterX,
    parameterY,
    parameterZ
).Compile();
Console.WriteLine(f(24, 6, 3)); // prints 42 to the console



2> Julien Ronca..:

只是为了使用CodeDom来获得乐趣(只要字符串中存在任何有效的C#代码,只要它存在于mscorlib中(根本不检查错误):

static class Program
{
    static string code = @"
        public static class __CompiledExpr__
        {{
            public static {0} Run({1})
            {{
                return {2};
            }}
        }}
        ";

    static MethodInfo ToMethod(string expr, Type[] argTypes, string[] argNames, Type resultType)
    {
        StringBuilder argString = new StringBuilder();
        for (int i = 0; i < argTypes.Length; i++)
        {
            if (i != 0) argString.Append(", ");
            argString.AppendFormat("{0} {1}", argTypes[i].FullName, argNames[i]);
        }
        string finalCode = string.Format(code, resultType != null ? resultType.FullName : "void",
            argString, expr);

        var parameters = new CompilerParameters();
        parameters.ReferencedAssemblies.Add("mscorlib.dll");
        parameters.ReferencedAssemblies.Add(Path.GetFileName(Assembly.GetExecutingAssembly().Location));
        parameters.GenerateInMemory = true;

        var c = new CSharpCodeProvider();
        CompilerResults results = c.CompileAssemblyFromSource(parameters, finalCode);
        var asm = results.CompiledAssembly;
        var compiledType = asm.GetType("__CompiledExpr__");
        return compiledType.GetMethod("Run");
    }

    static Action ToAction(this string expr)
    {
        var method = ToMethod(expr, new Type[0], new string[0], null);
        return () => method.Invoke(null, new object[0]);
    }

    static Func ToFunc(this string expr)
    {
        var method = ToMethod(expr, new Type[0], new string[0], typeof(TResult));
        return () => (TResult)method.Invoke(null, new object[0]);
    }

    static Func ToFunc(this string expr, string arg1Name)
    {
        var method = ToMethod(expr, new Type[] { typeof(T) }, new string[] { arg1Name }, typeof(TResult));
        return (T arg1) => (TResult)method.Invoke(null, new object[] { arg1 });
    }

    static Func ToFunc(this string expr, string arg1Name, string arg2Name)
    {
        var method = ToMethod(expr, new Type[] { typeof(T1), typeof(T2) },
            new string[] { arg1Name, arg2Name }, typeof(TResult));
        return (T1 arg1, T2 arg2) => (TResult)method.Invoke(null, new object[] { arg1, arg2 });
    }

    static Func ToFunc(this string expr, string arg1Name, string arg2Name, string arg3Name)
    {
        var method = ToMethod(expr, new Type[] { typeof(T1), typeof(T2), typeof(T3) },
            new string[] { arg1Name, arg2Name, arg3Name }, typeof(TResult));
        return (T1 arg1, T2 arg2, T3 arg3) => (TResult)method.Invoke(null, new object[] { arg1, arg2, arg3 });
    }

    static void Main(string[] args)
    {
        var f = "x + y * z".ToFunc("x", "y", "z");
        var x = f(3, 6, 8);

    }
}



3> Andrew Hare..:

C#没有这样的任何功能(其他语言 - 比如JavaScript - 有eval处理这样的东西的功能).您将需要解析字符串并使用表达式树或通过发送IL自己创建方法.

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有