2016-05-06 10 views
4

文字列を実行可能なコードに変換するソリューションを探しています。私のコードは極端に遅く、4.7 secondsで実行されます。これを行うより速い方法がありますか?文字列を実行可能なコードのパフォーマンスに変換する

文字列: "* 5"

出力:25

コード:まあ

class Program { 

    static void Main(string[] args) { 
     var value = "5 * 5"; 
     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 
     var test = Execute(value); 
     sw.Stop(); 
     Debug.WriteLine($"Execute string at: {sw.Elapsed}"); 
    } 

    private static object Execute(string content) { 
     var codeProvider = new CSharpCodeProvider(); 
     var compilerParameters = new CompilerParameters { 
      GenerateExecutable = false, 
      GenerateInMemory = true 
     }; 

     compilerParameters.ReferencedAssemblies.Add("system.dll"); 

     string sourceCode = CreateExecuteMethodTemplate(content); 
     CompilerResults compilerResults = codeProvider.CompileAssemblyFromSource(compilerParameters, sourceCode); 
     Assembly assembly = compilerResults.CompiledAssembly; 
     Type type = assembly.GetType("Lab.Cal"); 
     MethodInfo methodInfo = type.GetMethod("Execute"); 

     return methodInfo.Invoke(null, null); 
    } 

    private static string CreateExecuteMethodTemplate(string content) { 
     var builder = new StringBuilder(); 

     builder.Append("using System;"); 
     builder.Append("\r\nnamespace Lab"); 
     builder.Append("\r\n{"); 
     builder.Append("\r\npublic sealed class Cal"); 
     builder.Append("\r\n{"); 
     builder.Append("\r\npublic static object Execute()"); 
     builder.Append("\r\n{"); 
     builder.AppendFormat("\r\nreturn {0};", content); 
     builder.Append("\r\n}"); 
     builder.Append("\r\n}"); 
     builder.Append("\r\n}"); 

     return builder.ToString(); 
    } 
} 
+1

あなたは*実行コードではないことに注意してください。文字列を作成してからMSILにコンパイルし、次にJITtedを取得し、* then *実際に実行します。実際のパフォーマンスを測定する場合は、ベンチマークの外でコンパイルされたメソッドを作成します。ベンチマークを開始する前に 'RuntimeHelpers.PrepareDelegate'をJITに呼び出すこともできます。そして、平均時間を得るためにそれを連続して百万回呼び出す。 – Groo

+0

あなたはこのスレッドを見ましたか? http://stackoverflow.com/questions/234217/is-it-possible-to-compile-and-execute-new-code-at-runtime-in-net これは重複しているわけではありませんが、試してベンチマークするための良い代替アプローチをいくつか教えてください。 – zoubida13

+1

コンパイルは、コードを複数回実行する場合(つまり、複数回呼び出す場合やループがあるため)にのみ意味があります。コードを一度呼び出すとコードにループがない場合、コンパイルよりも解釈が速くなります。 – dasblinkenlight

答えて

5

、をハック簡単にあります:

var _Result = new DataTable().Compute("5*5"); // _Result = 25 
var _Result2 = new DataTable().Compute("5+5*5"); // _Result2 = 30 
は、

さらにオプションがあります。 Documentationをご覧ください。

+0

+1 OPが数学演算以上の処理を必要とする可能性はありますが、これは実際にはかなりクールなハックです。 :-D – Groo

+0

これは実際にはかなり涼しかったし、それは私の目的を満たしている "ハック"ですが:ありがとう – MrProgram

関連する問題