Exeを生成せずに、動的コードをコンパイルして実行しますか?
-
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を使用します。それは真にメモリvで動作します。他のソリューションのいくつかは、フードの下のファイルで書き戻して読み戻したと言及しています。
また、Python、Ruby、Luaなどのスクリプト言語を埋め込むこともご覧ください。これらはすべて、ディスクに何も書き込まずにメモリからコードを実行することをサポートしています。
ファイルを作成せずにC#をコンパイルして実行することは不可能ではないにしても困難です。あなたが探しているのは、ある種のスクリプト機能です。あなたがあなたの質問で説明したことは、本質的にの違いです 解釈 言語とa 編集済み 言語。見る ウィキペディア:スクリプト言語.
この機能を使用するものに応じて、Python、Ruby、Luaなどのスクリプト言語を非常に利用できます。これが例です: C#からPythonスクリプトを実行するにはどうすればよいですか?
これにより、アプリケーションがpython.exe(または選択したスクリプト言語を実行するために必要な実行可能ファイル)に依存します。それを避けたい場合は、注入されたスクリプトで必要なことに応じて、アプリケーションがランタイムを行う独自のスクリプト言語を作成するのはそれほど難しくないかもしれません。
編集:その最初の段落はごみです。ごめん。見る http://msdn.microsoft.com/en-us/library/8ffc3x75%28v = vs.110%29.aspx