Выполнение кода из textbox

169
27 августа 2021, 22:10

Помогите реализовать такую идею:
Ввожу в textbox1 определенный код и при нажатии на кнопку он выполняется.
Идеи с if(...) не подойдут

Например:
Ввожу в textbox: MessageBox.Show("Сообщение");
Нажимаю на кнопку
И выполняется этот код

Answer 1

А давайте воспользуемся новомодным Roslyn API.

Для начала, нам понадобится nuget-пакет Microsoft.CodeAnalysis.CSharp.Scripting, добавьте его через References → правая кнопка мыши → Manage NuGet Packages....

Теперь, сам скрипт. Модельный класс будет очень простым, т. к. всё уже написано за нас:

using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
class Script
{
    ScriptState state;
    public static async Task<Script> Create(
        IEnumerable<Assembly> references, IEnumerable<string> usings)
    {
        var options = ScriptOptions.Default.WithReferences(references).WithImports(usings);
        var state = await CSharpScript.RunAsync("", options);
        return new Script() { state = state };
    }
    public async Task<object> ExecuteNext(string code)
    {
        state = await state.ContinueWithAsync(code);
        return state.ReturnValue;
    }
}

Вот собственно и вся сложность.

Пользоваться так:

// какие DLL должны быть доступны?
static Assembly[] references = new[]
    {
        typeof(object).Assembly,
        typeof(Uri).Assembly,
        typeof(Enumerable).Assembly,
        typeof(MessageBox).Assembly
    };
// какие юзинги должны быть доступны?
static string[] usings = new[]
    {
        "System",
        "System.IO",
        "System.Text",
        "System.Windows"
    };
// инициализация
Script script = await Script.Create(references, usings);
// выполнение одной команды:
try
{
    var result = await script.ExecuteNext(cmd);
    LastResult = result?.ToString() ?? "<no output>";
    IsLastGood = true;
}
catch (CompilationErrorException ex)
{
    LastResult = string.Join(" // ", ex.Diagnostics);
    IsLastGood = false;
}

Я прикрутил простейший интерфейс, выглядит так:

Проект лежит здесь: https://github.com/vladd/EvalUITest

Различная полезная литература:

  • Scripting API Samples
  • In-memory C# compilation (and .dll generation) using Roslyn
  • Getting Started C# Syntax Analysis
  • Compiling C# Code Into Memory and Executing It with Roslyn
Answer 2
private void btnCompile_Click(object sender, EventArgs e)
{
    // Здесь код из твоего TextBox'а
    string code =
        @"class EntityCollection : System.Collections.Generic.List<Entity> {}
        class Entity
        {
        public string Name { get; set; }
            public int Age { get; set; }
        }";
    // Получаем интерфейс компилятора
    CSharpCodeProvider codeProvider = new CSharpCodeProvider();
    // Задаём параметры компиляции
    CompilerParameters compilerParameters = new CompilerParameters();
    compilerParameters.GenerateInMemory = true;
    compilerParameters.TreatWarningsAsErrors = false;
    compilerParameters.WarningLevel = 4;
    // Цепляем референсные сборки
    compilerParameters.ReferencedAssemblies.Add("System.dll");
    // Компилируем код
    CompilerResults results = codeProvider.CompileAssemblyFromSource(compilerParameters, code);
    if (results.Errors.Count > 0)
    {
        StringBuilder sbExceptions = new StringBuilder();
        foreach (CompilerError CompErr in results.Errors)
        {
            sbExceptions.AppendLine(
                "Line number " + CompErr.Line +
                ", Error Number: " + CompErr.ErrorNumber +
                ", ‘" + CompErr.ErrorText + ";" +
                Environment.NewLine + Environment.NewLine);
        }
        throw new Exception("Exception raised while compiling your code: nn" + sbExceptions);
    }
    // Получаем скопилированную сборку
    Assembly assembly = results.CompiledAssembly;
    // Ищем наш тип "EntityCollection"
    Type type = assembly.GetType("EntityCollection");
    // Создаём экземпляр этого класса
    IList list = (IList) Activator.CreateInstance(type);
    // Ищем наш второй тип и порождаем его экземпляр
    Type eType = assembly.GetType("Entity");
    object obj = Activator.CreateInstance(eType);
    // Задаём его свойства
    eType.GetProperty("Name").SetValue(obj, "Sanjay", null);
    eType.GetProperty("Age").SetValue(obj, 30, null);
    // Добавляем в нашу же коллецию
    list.Add(obj);
    // Делаем с ней что-нибудь
    dataGridView1.DataSource = list;
}

Исходная статья здесь.

READ ALSO
Как защитить sql insert от sql injection в python?

Как защитить sql insert от sql injection в python?

Как защитить такой insert запрос от sql инъекций ? Я использую python 37 и БД mysql 5

170
Table &#39;mydb.mytable&#39; doesn&#39;t exist in engine после перезапуска сервера

Table 'mydb.mytable' doesn't exist in engine после перезапуска сервера

Сегодня вечером мой сервер завис и перезапустился, после чего одна из табличек пострадала, и перестала работатьБекапа к сожалению нет

176
Как получить количество товаров для категории которая имеет подкатегории?

Как получить количество товаров для категории которая имеет подкатегории?

Есть таблица категорий: id, title, parent_id; Таблица товаров: id, name, category_id;

257