我在這裡看了幾個例子從一個Expression和MSDN上調用一個方法,但是我無法為下面的查詢獲得Any()的正確方法調用/對像類型。我似乎能夠獲得屬性調用但不能獲得子屬性的IEnumerable部分。
billing_map_set_lu是billmaps_lu的父級,並在實體框架中定義為關聯。
我使用表達式樹的原因是我需要能夠在運行時使用1-n .SelectMany(p => p.billmaps_lu).Where(謂詞)子句定義查詢。所以我想如果我可以構建表達式樹,我可以處理我對這個系統的所有不同組合,這些組合很多。
var myResults = ctx.billing_map_set_lu
.Where(p => p.billmaps_lu.Any(b => b.billmap_columnname == "templatesittings_key" && b.billmap_columnvalue == 428264))
SelectMany(p => p.billmaps_lu)
.Where (b =>b.billmap_columnname =="locations_key" && b.billmap_columnvalue == 12445)
Select(z => z.billing_map_set_lu);
我嘗試過使用上面的樣本進行了不少嘗試......
ParameterExpression bms = Expression.Parameter(typeof(billmaps_lu));
Expression left1 = Expression.Property(bms, typeof(billmaps_lu).GetProperty("billmap_columnname"));
Expression right1 = Expression.Constant("templatesittings_key", typeof(string));
Expression InsideAny1 = Expression.Equal(left1, right1);
Expression left2 = Expression.Property(bms, typeof(billmaps_lu).GetProperty("billmap_columnvalue"));
Expression right2 = Expression.Constant(428264, typeof(int));
Expression InsideAny2 = Expression.Equal(left2, right2);
Expression myWhereClause1 = Expression.AndAlso(InsideAny1, InsideAny2);
上面的部分似乎很好,但是當我嘗試做的時候.Any就像我無法獲得正確的屬性/方法來獲得正確的對象。 (我覺得我在處理一個物理問題,我正在使用錯誤的單位。)我希望它是一個簡單的我想念的,我對錶達樹很新。我已經包含了非工作代碼來嘗試告訴你我的頭在哪里以及某人如何引導我朝著正確的方向前進。
MethodInfo method = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(billing_map_set_lu).GetProperty("billmaps_lu").PropertyType);
ParameterExpression billMapSetParameter = Expression.Parameter(typeof(billing_map_set_lu), "p");
ParameterExpression billMaps = Expression.Parameter(typeof(billmaps_lu), "p1");
var myFunction = Expression.Lambda<Func<billmaps_lu, bool>>(Expression.Call(method, Expression.Property(billMapSetParameter, typeof(billing_map_set_lu).GetProperty("billmaps_lu")), myWhereClause1), billMaps)
免責聲明,我沒有任何編譯的工作代碼。
2個問題。
第一個問題可能在於:
ParameterExpression billMapSetParameter = Expression.Parameter(typeof(billing_map_set_lu), "p");
這不是您需要的參數:
Expression.Lambda<Func<billmaps_lu, bool>>(Expression.Call(method, Expression.Property(**billMapSetParameter**, typeof(billing_map_set_lu).GetProperty("billmaps_lu")), myWhereClause1), billMaps)
將billMapSetParameter更改為billMaps ParamterExpression,那麼你應該好好去。您正在調用PropertyExpression從ParameterExpression獲取您的billMapSet。
第二個問題:(不確定,但我的直覺)您可能需要將Where子句作為ConstantExpression傳遞,類型為Expression <.Func <>>。 .Any方法有兩個參數,其中第二個是Expression <.Func <>>(或者只是一個Func <>?不記得了)。
var whereExpression = Expression.Lambda<.Func<.billmaps_lu, bool>>(myWhereClause1, bms);
var ce = Expression.Constant(whereExpression)
然後將ce傳回原來你“myWhereClause1”所在的地方。
交叉手指工作
編輯 - 廢話,SHOW MI ZEH CODEZ
public class Foo
{
public List<string> Strings { get; set; }
}
class Program
{
static void Main(string[] args)
{
Func<Foo, bool> func =
a => a.Strings.Any(b => b == "asdf");
// b => b == "asdf";
var bParameter = Expression.Parameter(typeof (string));
var asdfConstant = Expression.Constant("asdf");
var compare = Expression.Equal(bParameter, asdfConstant);
var compareExpression = Expression.Lambda<Func<string, bool>>(compare, bParameter);
var ceCompareExpression = Expression.Constant(compareExpression.Compile());
// a => a.Strings.Any(compareExpression)
var parameter = Expression.Parameter(typeof (Foo));
var foosProperty = Expression.Property(parameter, typeof (Foo).GetProperty("Strings"));
MethodInfo method = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(string));
var anyMethod = Expression.Call(method, foosProperty, ceCompareExpression);
var lambdaExpression = Expression.Lambda<Func<Foo, bool>>(anyMethod, parameter);
// Test.
var foo = new Foo {Strings = new List<string> {"asdf", "fdsas"}};
Console.WriteLine(string.Format("original func result: {0}", func(foo)));
Console.Write(string.Format("constructed func result: {0}", lambdaExpression.Compile()(foo)));
Console.ReadKey();
}
}