2007年04月18日

C# eval先から自分の関数を呼び出させる

あんまりにも面白かったので作ってみた。

動的に 1+1+自分のクラスのAAAの値を求める。
サンプルでは、 AAA=13 なので、 1+1+13=15 と表示される。

自分

動的に作成したルーチン

自分の関数


これ使えば、簡易スクリプト言語なんて不要ぢゃねーの??

参考
文字列の計算式の計算結果を取得する
Evaluating Mathematical Expressions by Compiling C# Code at Runtime


using System;
using System.Collections.Generic;
using System.Text;

using System.CodeDom.Compiler;
using System.Reflection;

namespace @ref
{
//int AAA を保護するクラス
public class Himitsu
{
private int AAA;

public int getAAA()
{
return this.AAA;
}

public Himitsu(int inAAA)
{
this.AAA = inAAA;
}
};

public class Program
{
static private Himitsu HimitsuInstance;

public static int MyCallBack()
{
return HimitsuInstance.getAAA();
}
static void Main(string[] args)
{
//計算するためのコード
string source = @"
public class MainClass
{
public static double EVal()
{
int aaa = @ref.Program.MyCallBack(); //秘密の数字にアクセス
return 1+1+aaa;
}
}";

//秘密の数字13を渡す.
HimitsuInstance = new Himitsu(13);

//コンパイルするための準備
CodeDomProvider cp = new Microsoft.CSharp.CSharpCodeProvider();
ICodeCompiler icc = cp.CreateCompiler();
CompilerParameters cps = new CompilerParameters();
CompilerResults cres;
//メモリ内で出力を生成する
cps.GenerateInMemory = true;
cps.ReferencedAssemblies.Add("system.dll");
cps.ReferencedAssemblies.Add("ref.exe"); //自分自身のexe名
//コンパイルする
cres = icc.CompileAssemblyFromSource(cps, source);
if (cres.Errors.Count > 0)
{
string errors = "Compilation failed:\n";
foreach (CompilerError err in cres.Errors)
{
errors += err.ToString() + "\n";
}
Console.WriteLine(errors);
return;
}
//コンパイルしたアセンブリを取得
Assembly asm = cres.CompiledAssembly;
//MainClassクラスのTypeを取得
Type t = asm.GetType("MainClass");
//EValメソッドを実行し、結果を取得
double d = (double) t.InvokeMember("EVal",
BindingFlags.InvokeMethod,
null,
null,
null);

//結果を表示
Console.WriteLine(d);
}
}
}
posted by rti at 00:55 | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/39115135

この記事へのトラックバック