いくつかのコードを含む文字列string input;
があります(以下はすべてその文字列にあります)
var x = s.IndexOf("a");
return String.Format(s, x);
今、私は次のシナリオを達成したいと思います:
Func<string, string> f = Compile(input);
var test = "dcba - {0}";
var result = f(test);
// result = "dcba - 3";
実際の T1、TResult は既知 (ここでは文字列、文字列) であり、その入力の名前は "s" であると仮定します。私はこのようにそれを達成することができます:
var input = "var x = s.IndexOf(\"a\"); return String.Format(s, x);";
var containerClass = @"using System; class TempClass {{ public string temp_func(string s){{ {0} }} }}";
var code = String.Format(containerClass, input);
// Create a new instance of the C# compiler
var compiler = new CSharpCodeProvider();
var params = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true
};
params.ReferencedAssemblies.Add("System.dll");
var results = compiler.CompileAssemblyFromSource(params, code);
Func<string, string> f;
if (results.Errors.Count == 0)
{
f = s =>
{
var myClass = results.CompiledAssembly.CreateInstance("TempClass");
return (string) myClass.GetType().
GetMethod("temp_func").
Invoke(myClass, new object[] {s});
};
// test:
Console.WriteLine(f(Console.ReadLine()));
}
しかし、その方法はかなり複雑です。Func<T1, TResult>
コンパイルされたアセンブリ全体ではなく、クラスをインスタンス化する (または静的メソッドを呼び出す)だけが必要であることがわかっている場合、これを単純化する方法はありますか?
もちろん、このコードをうまくドレスアップすることもできます。ジェネリック クラスでラップし、T1、TResult 型名を取得してTempClass
テンプレートに入れます ( String.Format("public {0} temp_func({1} s)",typeof(TResult).Name, typeof(T1).Name);
)。乗り心地が滑らか...