web-dev-qa-db-ja.com

EXEを生成せずに、動的コードをコンパイルして実行しますか?

Exeファイルやその他のファイルを生成せずに、保存されたコードをコンパイルして実行できるかどうか疑問に思っていました。基本的には、メモリからファイルを実行します。

基本的に、メインアプリケーションにはいくつかのコード(変更される可能性のあるコード)が格納されており、コードをコンパイルして実行する必要があります。ファイルを作成せずに。

ファイルを作成し、プログラムを実行してから、ファイルを削除することはできません。コンパイルされたコードはメモリから実行する必要があります。

コード例、ポインタ、またはほとんど何でも大歓迎です:)

22
caesay
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[] { });
}

これにより、含まれているソースコード文字列から単純なクラスがコンパイルされ、クラスがインスタンス化されて、そのクラスで関数が反射的に呼び出されます。

36
Adam Robinson

System.Linq.Expressionsを使用してTimの回答に追加する方法の例を次に示します。明らかにそれは最も美しいコードではありませんが、この素敵なツリーのような形でそれを持っていると、開発がとても簡単になります。

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;
}
5
ChaosPandion

それが可能だ。書きたいコードの量と種類に応じて、簡単または難しいです。

  • 1行の式をコンパイルします: System.Linq.Expressions (簡単ですが制限されています)
  • プログラム全体をコンパイルします: System.Reflection.Emit (デバッグは難しいが、不可能ではない)

編集:。NET 4.0より前では、System.Linq.Expressionsは、C#の1行に収まるものに制限されます。つまり、if、while、変数の割り当てなどはありません。

4
Tim Robinson

はい、できます。とても遅いですが、確かにできます。 CodeDOMまたは.Netの(new CSharpCodeProvider().CreateCompiler())を見てください。

2
Brian Genisio

System.CodeDomを調べてください。それはあなたが探していることを正確に行います。

1
Seattle Leonard

Monoでは、CSharp.Evaluatorを使用します。これは、メモリ内で真に機能します。v。ボンネットの下でファイルに書き込み、読み取りを行う、前述の他のソリューションのいくつか。

0
user430788