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

Varagian

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

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

2 ответа

Varagian

А давайте воспользуемся новомодным 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

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

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

// какие 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;
}
</no>

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

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

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


Varagian

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;
}
</entity>

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

licensed under cc by-sa 3.0 with attribution.