Скомпилировать и запустить динамический код, не генерируя EXE?

StackOverflow https://stackoverflow.com/questions/3188882

  •  02-10-2019
  •  | 
  •  

Вопрос

Мне было интересно, можно ли скомпилировать и запустить сохраненный код, не генерируя EXE или какой -либо тип других файлов, в основном запустите файл из памяти.

По сути, основное приложение будет иметь некоторый сохраненный код (код, который потенциально будет изменен), и ему необходимо будет скомпилировать код и выполнить его. без создания файлов.

Создание файлов, запуск программы, а затем удаление файлов не является вариантом. Скомпилированный код должен быть запущен из памяти.

Примеры кода, или указатели, или почти все, что приветствуется :)

Это было полезно?

Решение

using (Microsoft.CSharp.CSharpCodeProvider foo = 
           new Microsoft.CSharp.CSharpCodeProvider())
{
    var res = foo.CompileAssemblyFromSource(
        new System.CodeDom.Compiler.CompilerParameters() 
        {  
            GenerateInMemory = true 
        }, 
        "public class FooClass { public string Execute() { return \"output!\";}}"
    );

    var type = res.CompiledAssembly.GetType("FooClass");

    var obj = Activator.CreateInstance(type);

    var output = type.GetMethod("Execute").Invoke(obj, new object[] { });
}

Это компилирует простой класс из строки исходного кода, а затем экземпляры класса и отражает функцию.

Другие советы

Вот пример того, как использовать System.Linq.Expressions Чтобы добавить к ответу Тима. Очевидно, что это не самый красивый код, но наличие его в этой красивой форме, подобной деревьям, делает разработку таким простым.

private  Expression<IsWordChar> CreateIsWordCharExpression()
{
    var e = Expression.Parameter(typeof(int), "e");
    var c = Expression.Variable(typeof(char), "c");
    var returnLabel = Expression.Label(Expression.Label(typeof(bool)), _falseConstant);
    var lambda = Expression.Lambda<IsWordChar>(
        Expression.Block(
            new[] { c },
            Expression.IfThen(
                Expression.OrElse(
                    Expression.Equal(e, Expression.Constant(-1)),
                    Expression.Equal(e, _inputLengthVar)
                ),
                Expression.Return(returnLabel.Target, _falseConstant)
            ),
            Expression.Assign(c, Expression.MakeIndex(_str, _stringCharsPropertyInfo, new[] { e })),
            Expression.IfThenElse(
                Expression.OrElse(
                    Expression.OrElse(
                        Expression.OrElse(
                            Expression.AndAlso(
                                Expression.GreaterThanOrEqual(c, Expression.Constant('a')),
                                Expression.LessThanOrEqual(c, Expression.Constant('z'))
                            ),
                            Expression.AndAlso(
                                Expression.GreaterThanOrEqual(c, Expression.Constant('A')),
                                Expression.LessThanOrEqual(c, Expression.Constant('Z'))
                            )
                        ),
                        Expression.AndAlso(
                            Expression.GreaterThanOrEqual(c, Expression.Constant('0')),
                            Expression.LessThanOrEqual(c, Expression.Constant('1'))
                        )
                    ),
                    Expression.Equal(c, Expression.Constant('_'))
                ),
                Expression.Return(returnLabel.Target, _trueConstant),
                Expression.Return(returnLabel.Target, _falseConstant)
            ),
            returnLabel
        ),
        "IsWordChar",
        new[] { e }
    );
    return lambda;
}

Возможно. Это легко или тяжело, в зависимости от того, сколько и какой код вы хотите написать.

  • Скомпилируйте однострочные выражения: System.Linq.Expressions (Прямо, но ограничен)
  • Составьте целые программы: System.Reflection.Emit (Трудно отлаживать, но не невозможно)

Редактировать: Обратите внимание, что до .NET 4.0, System.Linq.Expressions ограничено тем, что вы можете установить на одной строке C#: то есть, если, если, в то время как, назначение переменной и т. Д.

Да, ты можешь это сделать. Это очень медленно, но вы, конечно, можете это сделать. Посмотрите на кодедом или (new CSharpCodeProvider().CreateCompiler()) в .net.

Заглянуть в System.CodeDom. Отказ Это сделает именно то, что вы ищете.

В Mono вы используете csharp.evaluator. Это работает по -настоящему в памяти против. Некоторые из других решений упомянули, которые записывают и читают обратно в файл под капюшоном.

Также взгляните на внедрение языка сценариев, такого как Python, Ruby, Lua и т. Д. Все эти поддерживают выполнение кода из памяти, без того, чтобы на диск не было написано.

Трудно, если не невозможно компилировать и выполнять C# без создания файла, потому что ... ну, вот какой сборник превращает язык в исполняемый файл. То, что вы ищете, - это какая -то функциональность сценариев. То, что вы описали в своем вопросе, по сути разница между интерпретируется Язык и а составлено язык. Видеть Википедия: язык сценариев.

В зависимости от того, для чего вы будете использовать эту функцию, вы можете отлично использовать язык сценариев, такой как Python, Ruby или Lua. Вот пример: Как запустить сценарий Python от C#?

Это сделало бы ваше приложение зависеть от Python.exe (или любого исполняемого файла, которое вам нужно для запуска выбранного вами языка сценариев). Если вы хотите избежать этого, может быть не слишком сложно сделать свой собственный язык сценариев, для которого ваше приложение выполняет во время выполнения, в зависимости от того, что вам нужно сделать со своим инъецированным сценарием.

Редактировать: этот первый абзац - мусор. Извини. Видеть http://msdn.microsoft.com/en-us/library/8ffc3x75%28v=vs.110%29.aspx

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top