70

式ツリーは素晴らしい機能ですが、その実用的な用途は何ですか?それらは、ある種のコード生成やメタプログラミングなどに使用できますか?

4

7 に答える 7

45

Jon が指摘しているように、私はそれらを使用して、.NET 3.5 で汎用演算子を提供しています。Delegate.CreateDelegateまた、(再び MiscUtil で) それらを使用して、既定以外のコンストラクター (コンストラクターでは使用できませんが、正常に動作します) への高速アクセスを提供しますExpression

手動で作成された式ツリーのその他の用途:

しかし実際には、Expression は動的コードを記述するための非常に用途の広い方法です。よりもはるかReflection.Emitに単純で、私のお金では、CodeDOM よりも理解しやすいです。.NET 4.0 では、さらに多くのオプションを利用できます。Expression 私のブログで、コードを書くための基礎を紹介しています。

于 2008-12-31T15:32:46.343 に答える
22

Marc Gravell は、MiscUtilで汎用演算子を実装するためにそれらを使用して大きな効果を上げました。

于 2008-12-31T14:48:48.023 に答える
15

みなさんと共有したい式ツリーを使用して、一般的なフィルター関数を作成しました...

始める

var allFiltered= Filter(AllCustomer, "Name", "Moumit");

public static List<T> Filter<T>(this List<T> Filterable, string PropertyName, object ParameterValue)
{
    ConstantExpression c = Expression.Constant(ParameterValue);
    ParameterExpression p = Expression.Parameter(typeof(T), "xx");
    MemberExpression m = Expression.PropertyOrField(p, PropertyName);
    var Lambda = Expression.Lambda<Func<T, Boolean>>(Expression.Equal(c, m), new[] { p });
    Func<T, Boolean> func = Lambda.Compile();
    return Filterable.Where(func).ToList();
}

ワン・モア

string singlePropertyName=GetPropertyName((Property.Customer p) => p.Name);

public static string GetPropertyName<T, U>(Expression<Func<T, U>> expression)
{
        MemberExpression body = expression.Body as MemberExpression;
        // if expression is not a member expression
        if (body == null)
        {
            UnaryExpression ubody = (UnaryExpression)expression.Body;
            body = ubody.Operand as MemberExpression;
        }
        return string.Join(".", body.ToString().Split('.').Skip(1));
}

より拡張可能にする

string multiCommaSeparatedPropertyNames=GetMultiplePropertyName<Property.Customer>(c => c.CustomerId, c => c.AuthorizationStatus)

public static string GetMultiplePropertyName<T>(params Expression<Func<T, object>>[] expressions)
{
        string[] propertyNames = new string[expressions.Count()];
        for (int i = 0; i < propertyNames.Length; i++)
        {
            propertyNames[i] = GetPropertyName(expressions[i]);
        }

        return propertyNames.Join();
}

リフレクションを使用しても実行できることはわかっていますが、これは非常に高速であるか、最初のコンパイル後のラムダと同等であると言えます。最初の反復は平均 10 ミリ秒しかかかりません。これが Expression Tree マジックです。シンプルで素晴らしい(と思います)!

于 2013-12-09T11:57:33.743 に答える
12

私はそれらを使用して、データの並べ替えまたはフィルター処理の動的クエリを作成します。例として:

IQueryable<Data.Task> query = ctx.DataContext.Tasks;

if (criteria.ProjectId != Guid.Empty)
      query = query.Where(row => row.ProjectId == criteria.ProjectId);

if (criteria.Status != TaskStatus.NotSet)
      query = query.Where(row => row.Status == (int)criteria.Status);

if (criteria.DueDate.DateFrom != DateTime.MinValue)
      query = query.Where(row => row.DueDate >= criteria.DueDate.DateFrom);

if (criteria.DueDate.DateTo != DateTime.MaxValue)
     query = query.Where(row => row.DueDate <= criteria.DueDate.DateTo);

if (criteria.OpenDate.DateFrom != DateTime.MinValue)
     query = query.Where(row => row.OpenDate >= criteria.OpenDate.DateFrom);

var data = query.Select(row => TaskInfo.FetchTaskInfo(row));
于 2008-12-31T15:38:08.437 に答える
8

LINQ プロバイダーの実装は、ほとんどの場合、式ツリーを処理することによって行われます。コードからリテラル文字列を削除するためにも使用しています。

于 2008-12-31T14:49:41.453 に答える
4

それらを使用して、Google、Flickr、Amazon などの Web サイト、独自の Web サイト、または別のデータ プロバイダー用の独自の linq プロバイダーを構築できます。

于 2008-12-31T14:47:17.230 に答える
2

もともとJomoFisherによって、GustavoGuerraは静的文字列辞書の改訂版を公開しました。

式ツリーを介して、実際に(ばかばかしいほど)辞書を提供する動的な式。

実装は、入力文字列の長さ、最初の文字、2番目の文字というように、現在の値を選択する動的決定木を作成します。

これは最終的に、同等の辞書よりもはるかに高速に実行されます。

于 2008-12-31T16:06:08.677 に答える