Regexのテスターみたいに、Linqのテスターを作ろうと思ったら、StringからLinqする術がわからなかった。
ので、ゴリゴリ手書き。もっと良い方法があればフィードバックプリーズ。
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using Microsoft.CSharp;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("====== String文字列からLinq実行。 ======");
// パート1
var data1 = new Int32[] { 10, 11, 14, 18, 19, 21, 22, 28 };
Console.Write("データ1: ");
foreach (var value in data1) Console.Write(value + ",");
Console.WriteLine();
var res1 = LinqFrom<Int32>("from v in data where predicater(v) select v;"
, "TempNamespace", "TempClass", "TempFunc"
, data1, delegate(Int32 v) { return v % 2 == 0; });
Console.Write("データ1の偶数要素: ");
foreach (var value in res1) Console.Write(value + ",");
Console.WriteLine();
Console.WriteLine();
// パート2
var data2 = new String[] { "RedHat", "Fedora", "Mac", "Windows XP", "Windows Vista" };
Console.Write("データ2: ");
foreach (var value in data2) Console.Write(value + ",");
Console.WriteLine();
var res2 = LinqFrom<String>("from v in data where predicater(v) select v;"
, "TempNamespace", "TempClass", "TempFunc"
, data2, delegate(String v) { return v.StartsWith("Windows"); });
Console.Write("データ2のWindows: ");
foreach (var value in res2) Console.Write(value + ",");
Console.WriteLine();
}
public static IEnumerable<T> LinqFrom<T>(String linqText, String tempNamespace, String tempClassName, String tempFuncName, IEnumerable<T> data, Predicate<T> predicater)
{
CodeDomProvider provider = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
CompilerParameters cp = new CompilerParameters();
cp.GenerateInMemory = true;
cp.ReferencedAssemblies.Add("System.Core.dll");
cp.ReferencedAssemblies.Add("System.Xml.Linq.dll");
String compileSource =
"using System.Linq;" + System.Environment.NewLine
+ "namespace " + tempNamespace + " {" + System.Environment.NewLine
+ " public class " + tempClassName + System.Environment.NewLine
+ " {" + System.Environment.NewLine
+ " public System.Collections.Generic.IEnumerable<" + typeof(T).FullName + "> " + tempFuncName + "(System.Collections.Generic.IEnumerable<" + typeof(T).FullName + "> data, System.Predicate<" + typeof(T).FullName + "> predicater)" + System.Environment.NewLine
+ " {" + System.Environment.NewLine
+ " return " + linqText + System.Environment.NewLine
+ " }" + System.Environment.NewLine
+ " }" + System.Environment.NewLine
+ "}" + System.Environment.NewLine;
CompilerResults cr = provider.CompileAssemblyFromSource(cp, compileSource);
if (cr.Errors.HasErrors)
{
throw new System.Exception("構文エラーらしいよ。");
}
else
{
Assembly asm = cr.CompiledAssembly;
Type tempClassType = asm.GetType(tempNamespace + "." + tempClassName);
Object classInstance = Activator.CreateInstance(tempClassType);
MethodInfo methodInfo = tempClassType.GetMethod(tempFuncName);
Object result = methodInfo.Invoke(classInstance, BindingFlags.InvokeMethod, null, new Object[] { data, predicater }, CultureInfo.CurrentCulture);
return (System.Collections.Generic.IEnumerable<T>)result;
}
}
}