これは、言語の第一人者である私の同僚に触発されたもので、良い使い方を見つけられないようでした.
これらの概念は、実用的な理由を理解すれば、より簡単に流れていく傾向があることがわかりました。
現時点では、Linq プロバイダーを作成できるようにすることが唯一の目的のように見えますか?
それですか??これには他に何か利点がありますか?
これは、言語の第一人者である私の同僚に触発されたもので、良い使い方を見つけられないようでした.
これらの概念は、実用的な理由を理解すれば、より簡単に流れていく傾向があることがわかりました。
現時点では、Linq プロバイダーを作成できるようにすることが唯一の目的のように見えますか?
それですか??これには他に何か利点がありますか?
式ツリーは、コードをデータのように扱うことができるため、非常に強力です。ユーザーは、データを構築し、保存して、後で戻ってくることに慣れています。
式ツリーを使用すると、コードでも同じことができます。たとえば、ユーザーの入力(チェックボックス、数値範囲など)を取得して、それを式ツリーに変換できます。その後、その式ツリーを実行したり、後で使用するために保存したりできます。とてもかっこいい。
データフィルターやデータマッピングの構築や保存など、レポートに関する実際の使用法を考えてみてください。もう1つの実用的な使用法は、ユーザー定義のルールに基づいてアプリケーションでカスタムワークフローをサポートすることです。
式ツリーのシリアル化に関するMSDNコード( http://code.msdn.microsoft.com/exprserialization )を少し紹介します。これにより、アイデアが流れるようになります。
式ツリーを使用して、ドメイン言語を実行可能コードに変換できます。
問題を探している解決策ですか?
式ツリーを使用すると、コードを変換可能なデータ構造として提示できるため、言語間の変換に最適です。LinqToSQLは現在最も強力です。
DSL(変換)以外の別の用途は並列化(分割)であり、その分野での例はPLINQです。
.NET 4.0 式ツリーは、DLR AST の基礎でもあります
簡単な答えは、「いいえ、今は LINQ プロバイダーだけのものではありません」です。まず、動的言語をサポートするために、動的言語ランタイムによって式ツリーが拡張されました。基本的に、(IronPython や IronRuby が行ったように) 独自の動的言語を .NET に移植する場合は、式ツリーを使用する必要があります。OK、多くの人が自分の言語を持っているわけではありません。その他のユースケースは?その 1 つは、実行時に動的コードを生成することです。ここに例があります: Visual Studio 2010 で式ツリーを使用して動的メソッドを生成します。動的メソッドを作成するために、MSIL を生成する代わりに ET を使用する方法について説明します。実際、.NET 3.5 でも LINQ 以外の式ツリーのユース ケースがいくつかありますが、それらの投稿はまだ作成されていません。
私は、ドメイン固有言語のASTを式ツリーに変換するという良い経験をしました。また、 ANTLRツリーアダプタを使用すると、文法から直接式ツリーを作成するのもかなり簡単です。
この投稿を参照してください:http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx これは素晴らしいユースケースです。
アセンブリ エミットよりも高い抽象化レベルを持ち、CodeCompiler よりも高速なコード ビルダーとして式ツリーを使用できます。これは、CodeCompiler の代わりとして使用するようにチームを説得するために使用した概念の証拠です。
[TestClass]
public class WhenINeedToAccessPropertiesByNameHavingATypeReference
{
public class SomeCategoryData
{
public DateTime CreatedDate { get; set; }
}
[TestMethod]
public void ICanDoThatWithAnExpressionAndItPerformsWell()
{
// INIT
var someCategoryData =
Enumerable.Range(1970, 100).Select(year =>
new SomeCategoryData { CreatedDate = new DateTime(year, 1, 1) }).Cast<object>();
var t = typeof(SomeCategoryData); // or it can be: t = someCategoryData.First().GetType();
var compiled = Stopwatch.StartNew();
// ACT
var filter = AccessPropertyByNameInCompiledMannerSomehow(t, "CreatedDate");
// ASSERT
Trace.WriteLine(string.Format("compiled in: {0}", compiled.Elapsed));
Assert.IsTrue(compiled.ElapsedMilliseconds < 3, "compiles fast enough");
var executed = Stopwatch.StartNew();
// ACT
List<object> result = null;
for (var i = 0; i < 10000; i++)
{
result = someCategoryData.Where(d => filter(d, new DateTime(2000, 1, 1), new DateTime(2009, 1, 1)))
.ToList();
}
executed.Stop();
Trace.WriteLine(string.Format("executed in: {0}", executed.Elapsed));
// ASSERT
Assert.AreEqual(10, result.Count, "insure compiled code actually works");
Assert.IsTrue(executed.ElapsedMilliseconds < 300, "runs fast enough");
}
private static Func<object, DateTime, DateTime, bool>
AccessPropertyByNameInCompiledMannerSomehow(Type t, string fieldToFilterBy)
{
var objectParameter = Expression.Parameter(typeof(object), "p");
var instance = Expression.Convert(objectParameter, t);
var lower = Expression.Parameter(typeof(DateTime), "l");
var upper = Expression.Parameter(typeof(DateTime), "u");
var composite = Expression.Lambda<Func<object, DateTime, DateTime, bool>>(
Expression.And(
Expression.LessThanOrEqual(
lower,
Expression.PropertyOrField(instance, fieldToFilterBy)
),
Expression.GreaterThanOrEqual(
upper,
Expression.PropertyOrField(instance, fieldToFilterBy)
)
), objectParameter, lower, upper
);
return composite.Compile();
}
}
ここにはいくつかの例があります
(壊れたコードのフォーマットについて申し訳ありません)