динамическое ключевое слово в строковом вводе во время компиляции CodeDom

чтобы преобразовать строку в код, я использовал компилятор 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)  

компиляция завершается неудачно, и сообщения об ошибке нет!
Кажется, мне не хватает ссылки!
Ключевое слово dynamic доступно для .net 4.0
Я уже писал:

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

Но никакого результата!

Пожалуйста, помогите мне!


person IremadzeArchil19910311    schedule 10.03.2016    source источник


Ответы (1)


Класс 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");
    }
}
person Siderite Zackwehdex    schedule 10.03.2016
comment
Еще раз спасибо. кажется нашел! Было 3 ошибки, когда я написал динамическое ключевое слово вместо int..... - person IremadzeArchil19910311; 10.03.2016
comment
У меня есть эти 3 ошибки по результатам.Errors.Count - person IremadzeArchil19910311; 10.03.2016
comment
Да, для первой проблемы нужно добавить cp.ReferencedAssemblies.Add(Microsoft.CSharp.dll) - person Siderite Zackwehdex; 10.03.2016
comment
точно! Еще раз спасибо! - person IremadzeArchil19910311; 10.03.2016
comment
Но как быть с параметрами? Почему он снова показывает мне, что: «System.Int32 []» не может быть преобразован в тип «System.Object []» - person IremadzeArchil19910311; 10.03.2016
comment
Если я наберу String2LineOfCommand(P[0].ToString() + P[1].ToString(), 2, 4); - person IremadzeArchil19910311; 10.03.2016
comment
Вместо String2LineOfCommand(P[0].ToString() + P[1].ToString(), new [] { 2, 4}); - person IremadzeArchil19910311; 10.03.2016
comment
Я посмотрю... В mscorlib.dll произошло необработанное исключение типа "System.Reflection.TargetParameterCountException". Дополнительная информация: Несоответствие количества параметров. - person IremadzeArchil19910311; 10.03.2016
comment
Еще раз спасибо! Я узнаю! Я должен написать function.Invoke(null, new[] {P}); - person IremadzeArchil19910311; 10.03.2016