none
Динамическая компиляция кода C# RRS feed

  • Вопрос

  • В основном приложении создаем текстовый фрагмент кода на C#, компилируем средствами System.CodeDom.Compiler и запускаем.
    Все работает, но у меня, получается, только выводить сообщения.
    Вопрос: Как из компилируемого фрагмента добраться до переменных, объектов и др. основного приложения.

    • Перемещено Tagore Bandlamudi 1 октября 2010 г. 22:32 MSDN Forums consolidation (От:Visual C#)
    7 марта 2010 г. 14:07

Ответы

Все ответы

  • используйте рефлексию

    7 марта 2010 г. 15:04
  • Наверное я вас неправильно понял
    если вам нужно из компилируемого кода получить доступ к внешним объектам,
    тогда вы в компилируемом коде должны сослаться на внешние объекты, подключить необходимые сборки пример, где показаны основные этапы

    насчет рефлексии, в интернете очень много материала, например.
    все сведется к получению типа объекта, а дальше с ним можно делать что угодно,
    получить конструктор, создать объект, вызвать метод...
    но это вам не нужно


    Опишите задачу более подробно
    7 марта 2010 г. 21:56
  • Этот вопрос я подробно изложил на другом форуме:
    http://simple-cs.ru/forum/messages.aspx?topic=243

    Там есть исходный код и конкретный вопрос.
    Если можно посмотрите, пожалуйста.
    8 марта 2010 г. 16:16
  • понятно.
    в простейшем случае можно поступить так.
    в текстовом поле - вы не вводите ничего кроме кода, т.е. тела метода.
    например у вас есть 2 переменные

    string header="class MyFormulaClass
    {
    public void Calculate()
    {";

    string footer = "}}";

    далее в поле текстбокса вы вводите
    Console.WriteLine("HelloWorlds");

    после чего компиляция будет выглядеть так

    ...
    string codeToCompile = header+textBox1.Text+footer;
    result = provider.CompileAssemblyFromSource( cparams , codeToCompile );
    ...

    я думаю принцип понятен.
    теперь вам ничего не мешает изменить header таким образом, что там будет значение переменной x, например

    string header="class MyFormulaClass
    {
    public void Calculate()
    { int x ="+x.ToString() +";";

    все, теперь ваш код из текстбокса может быть таким

    int y = 3+x;
    Console.WriteLine(y);

    таким образом вы сошлетесь на значение переменной х :)
    8 марта 2010 г. 16:46
  • Да, я могу в текстовое поле ввести любой код и описать любые переменные и произвести с ними любые действия и распечатать!!!
    Например, если в текстовое поле ввести:
     
    using System;
    class MyFormulaClass
    {
    public void Calculate()
    {
    double a = 1.6;
    double b = 1.2;
    double c = Math.Sin(a) * Math.Cos(b);
    System.Windows.Forms.MessageBox.Show(Convert.ToString(c));
    }
    }

    Нажать на кнопку в окошке сообщения получим: 0.362203246232278

    Но мне нужно передать результат в обратно в основное приложение!!!
    Переменная double x = 0; существует в основном приложении.

    Грубо говоря x = c;
    где x - переменная основного приложения
    с - переменная динамического кода.
    Я пробовал через буфер обмена, но это не надежно.
    А черз файл неудобно и долго.
    Дожны же быть нормальные способы?

    Может быть как-то х создать по-особенному "глобально"?
    Я пробовал использовать обращение через пространство имен:

    using vcs011;
    ...
    vcs011.x = ...
    или
    vcs011.Form1.x = ...
    Идут ошибки
    8 марта 2010 г. 18:03
  • попробуйте так :)

    в текстбоксе:

    using System;
    class MyFormulaClass
    {
    public double Calculate()
    {
    double a = 1.6;
    double b = 1.2;
    double c = Math.Sin(a) * Math.Cos(b);
    return c;
    }
    }

    в коде

    double calcResult = (double)instance.GetType().InvokeMember("Calculate", ... );

    вот вы и получили результат из кода.
    также можно поступить, записав результат в переменную класса, потом взяв ее оттуда, как вам удобнее

    • Предложено в качестве ответа Nikonorov Evgeniy 9 марта 2010 г. 10:20
    • Отменено предложение в качестве ответа hellokol 9 марта 2010 г. 10:48
    • Помечено в качестве ответа hellokol 9 марта 2010 г. 10:52
    • Снята пометка об ответе hellokol 10 марта 2010 г. 7:27
    • Предложено в качестве ответа Nikonorov Evgeniy 10 марта 2010 г. 15:49
    9 марта 2010 г. 10:18
  • Большое спасибо!!! Все работает.


    Можно еще один вопрос?
    Как предать аргументы из основного кода в динамический:

    using System;
    class MyFormulaClass
    {
    public double Calculate(double adouble b)
    {
     double c = Math.Sin(a) * Math.Cos(b);
    return c;
    }
    }


    Дело в том, что каждый раз компилировать при смене значения аргумента очень долго.
    9 марта 2010 г. 10:49

  • double calcResult = (double)instance.GetType().InvokeMember("Calculate", ... );


    Одна из перегрузок этого метода принимает набор аргументов
    10 марта 2010 г. 14:17
  • double calcResult = (double)instance.GetType().InvokeMember("Calculate", System.Reflection.BindingFlags.InvokeMethod, null, instance, null); 
    Вот исходная строка, которая вызывает метод из динамического кода без аргументов.
    Что конкретно изменить или дописать, чтобы передавались два аргумента?
    10 марта 2010 г. 15:04
  • Попробуйте

    double result = (double)obj.GetType().InvokeMember("Calculate", BindingFlags.InvokeMethod, null, obj, new object[] { 1.0 , 2.0 });
    • Помечено в качестве ответа hellokol 10 марта 2010 г. 15:46
    10 марта 2010 г. 15:31
  • Огромное спасибо!!! Все заработало.

    10 марта 2010 г. 15:44
  • если вы будете несколько раз использовать один и тот же шаблон - то вы можете компилировать метод в сборку и сохранять его в приложении, таким образом сэкономите время на перекомпиляцию.
    подумайте об интерфейсах. если известен интерфейс метода, входные и выходные параметры, а тело метода может изменятся.
    вы сможете динамически приводить скомпилированный класс к интерфейсу,
    это распространенная практика.
    итого:
    1. выделите интерфейсы
    2. компилирйуйте и сохраняйте
    3. приводите к интерфейсам и повторно используйте
    • Предложено в качестве ответа Nikonorov Evgeniy 10 марта 2010 г. 15:49
    10 марта 2010 г. 15:44