CodeDom编译期间字符串输入中的动态关键字

时间:2016-03-10 12:34:50

标签: c# dynamic compilation codedom runtime-compilation

为了将字符串转换为代码,我使用的是CodeDom编译器 我在谈论在运行时编译C#代码!
特别是我想用几个参数进行运行编译,哪些类型可以不同。

    using System;
    using System.CodeDom;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Data;
    using System.Diagnostics;
    using System.Dynamic;
    using System.Net;
    using System.Reflection;
    using Microsoft.CSharp;

    static void Main()
    {
         String2LineOfCommand("P[0].ToString() + P[1].ToString()", new [] { 2, 4});
    }

    private void String2LineOfCommand(string expresion1, params object[] P)
    {
        MethodInfo function = CreateFunction(expresion1);
        object result = function.Invoke(null, P);
        Console.WriteLine(result.ToString());
    }

    public static MethodInfo CreateFunction(string function)
    {
        string code1 = @"
                        using System;
                        using System.Collections.Generic;
                        using System.Reflection;
                        using System.Dynamic;

                        namespace UserFunctions
                        {                
                            public class ParametricFunctions
                            {                
                                  public static object Function1(params int[] P)
                                  {
                                       return " +  function + @";
                                  }
                             }
                         }
                       ";

        var providerOptions = new Dictionary<string, string>();
        providerOptions.Add("CompilerVersion", "v4.0");

        CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
        CompilerParameters cp = new CompilerParameters();
        cp.GenerateInMemory = true;
        cp.TreatWarningsAsErrors = false;
        cp.ReferencedAssemblies.Add("System.dll");
        cp.ReferencedAssemblies.Add("System.Core.dll");
        cp.ReferencedAssemblies.Add("System.Windows.dll");
        cp.ReferencedAssemblies.Add("System.Dynamic.dll");

        CompilerResults results = provider.CompileAssemblyFromSource(cp, code1);

        Type parametricFunction1 = results.CompiledAssembly.GetType("UserFunctions.ParametricFunctions");
        return parametricFunction1.GetMethod("Function1");
    }

此代码工作得很好!
但正如我在谈论int类型参数之前告诉你的那样 我在运行时讨论不同情况下不同类型的输入参数!

如果我要输入

     String2LineOfCommand("P[0].ToString() + P[1].ToString()", 2, 4);

而不是

     String2LineOfCommand("P[0].ToString() + P[1].ToString()", new [] { 2, 4});

然后我会收到一条错误消息:

   An unhandled exception of type 'System.Reflection.TargetParameterCountException' occurred in mscorlib.dll
   Additional information: Parameter count mismatch.

请告诉我原因?

还要看看......

       public static MethodInfo CreateFunction(string function)  

当我尝试输入

       public static object Function1(params object[] P) 

而不是

       public static object Function1(params int[] P)

它显示了一条错误消息:

      An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
      Additional information: Object of type 'System.Int32[]' cannot be converted to type 'System.Object[]'.  

但是当我尝试输入

      public static object Function(params dynamic[] P)  

编译失败,没有关于错误的消息!
我想我错过了一个参考!
动态关键字适用于.net 4.0
我已写过:

      providerOptions.Add("CompilerVersion", "v4.0");

但没有结果!

请帮助我!

1 个答案:

答案 0 :(得分:2)

CompilerResults类具有Errors属性。编译失败的错误就在那里。

代码使它适用于动态(或对象,我不会在这里看到动态点):

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using Microsoft.CSharp;

public class Program
{

    static void Main()
    {
        String2LineOfCommand("P[0].ToString() + P[1].ToString()", 2, 4);
    }

    private static void String2LineOfCommand(string expresion1, params dynamic[] P)
    {
        MethodInfo function = CreateFunction(expresion1);
        object result = function.Invoke(null, new[] { P });
        Console.WriteLine(result.ToString());
        Debug.WriteLine(result.ToString());
    }

    public static MethodInfo CreateFunction(string function)
    {
        string code1 = @"
                        using System;
                        using System.Collections.Generic;
                        using System.Reflection;
                        using System.Dynamic;

                        namespace UserFunctions
                        {                
                            public class ParametricFunctions
                            {                
                                  public static object Function1(dynamic[] P)
                                  {
                                       return " + function + @";
                                  }
                             }
                         }
                       ";

        var providerOptions = new Dictionary<string, string>();
        providerOptions.Add("CompilerVersion", "v4.0");

        CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
        CompilerParameters cp = new CompilerParameters();
        cp.GenerateInMemory = true;
        cp.TreatWarningsAsErrors = false;
        cp.ReferencedAssemblies.Add("System.dll");
        cp.ReferencedAssemblies.Add("System.Core.dll");
        cp.ReferencedAssemblies.Add("System.Windows.dll");
        cp.ReferencedAssemblies.Add("System.Dynamic.dll");
        cp.ReferencedAssemblies.Add("Microsoft.CSharp.dll");

        CompilerResults results = provider.CompileAssemblyFromSource(cp, code1);

        Type parametricFunction1 = results.CompiledAssembly.GetType("UserFunctions.ParametricFunctions");
        return parametricFunction1.GetMethod("Function1");
    }
}