是否可以从字符串中创建c#中的匿名方法?
例如,如果我有一个字符串"x + y * z"
,才有可能把它变成某种方法/λ对象,我可以任意拨打x
,y
,z
参数?
这是可能的,是的.您必须解析字符串,例如,使用表达式树编译委托.
这是(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); Funcf = Expression.Lambda > ( addXMultiplyYZ, parameterX, parameterY, parameterZ ).Compile(); Console.WriteLine(f(24, 6, 3)); // prints 42 to the console
只是为了使用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 FuncToFunc (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); } }
C#没有这样的任何功能(其他语言 - 比如JavaScript - 有eval
处理这样的东西的功能).您将需要解析字符串并使用表达式树或通过发送IL自己创建方法.