簡體   English   中英

轉換表達式 <Func<T, object> &gt;表達 <Func<object> &gt;

[英]Convert Expression<Func<T, object>> to Expression<Func<object>>

如何轉換: Expression<Func<T, object>>Expression<Func<object>>

例如:

public class Entity
{        
    public virtual long Id { get; set; }
}

起源:

Expression<Func<Entity, object>> origin = x => x.Id;

目的地:

Entity alias = null;
Expression<Func<object>> destination = () => alias.Id;

原因:

實際上,我正在嘗試為Nhibernate創建一個自定義的可緩存ResultTransformer。 有一個public QueryOverProjectionBuilder<T> WithAlias(Expression<Func<object>> alias); 但是在我的類中,對於每個特定實體,我想使用更特定的選擇器,例如Expression<Func<T, object>>

您有兩種選擇:

  1. 按照Luaan的建議調用表達式
  2. 將參數替換為所需的值(常數或其他表達式)

選項1與Expression.Invoke一樣簡單,但可能與LINQ等庫不兼容。 選項2最好使用表達式訪問者來完成:

    private class ExchangeParametersVisitor : ExpressionVisitor
    {
        public ParameterExpression Parameter { get; set; }
        public Expression Value { get; set; }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            if (node == Parameter)
            {
                return Value;
            }
            return node;
        }
    }

您需要做的是將訪問者應用於lambda表達式的主體,並使用它來創建一個新的lambda表達式,該表達式包含與之前相同的所有參數,但您替換的參數除外。

這就是Expression.Invoke目的。

創建一個新的lambda表達式,然后對原始表達式使用Expression.Invoke組成兩個表達式。

樣品:

Expression<Func<string, int>> inner = x => int.Parse(x);
var outer = Expression.Lambda<Func<int>>
              (Expression.Invoke(inner, Expression.Constant("123")));

outer.Compile()().Dump(); // 123

遺憾的是,某些表達式解析器無法正確處理Invoke他們認為它是方法的調用,並拒絕它。 在這種情況下,您需要內聯表達式。 這意味着訪問整個內部表達式,並在更好的情況下用變量替換ParameterExpression ,或者如果解析器也不支持,則在所有位置插入參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM