list.Where(x => x > 0) みたいなのから from x in list where x > 0 select x を復元
タイトルどおり、式木からクエリ式を復元するようなプログラムを書いてみた。
http://ufcpp.net/study/csharp/source/ExpressionTree.zip
QueryExpression.cs が件の処理をしてる部分。
以下のようなコードで、
var q0 = Make.Expression((IEnumerable<int> five) => from baker in five from cooper in five from fletcher in five from miller in five from smith in five where Distinct(baker, cooper, fletcher, miller, smith) where baker != 5 where cooper != 1 where fletcher != 1 && fletcher != 5 where miller > cooper where Discrete(smith, fletcher) where Discrete(fletcher, cooper) select new { baker, cooper, fletcher, miller, smith } ); var q = new QueryExpression(q0); foreach (var l in q.Queries) { Console.Write("{0}\n", l); }
以下のような出力を得ます。
from baker in five from cooper in five from fletcher in five from miller in five from smith in five where Distinct(new [] {baker, cooper, fletcher, miller, smith}) where (baker != 5) where (cooper != 1) where ((fletcher != 1) && (fletcher != 5)) where (miller > cooper) where Discrete(smith, fletcher) where Discrete(fletcher, cooper) select new <>f__AnonymousType5`5(baker, cooper, fletcher, miller, smith)
匿名型を使った member init のところに <>f__AnonymousType5 ってのが出てる以外は元と一致。
これを使えば、クエリ式を機械的に最適化(where を極力上に持ってきたり、foreach, if, yield retrun に置き換えたり)できるはず。
.Cast とか .GroupBy とか、対応した方がよさそうだけど未対応のものもいくらかあり。