好吧,我承認我還沒有完全“獲得”lambda表達式和LINQ表達式樹;我正在做的很多事情就是切割和粘貼,看看哪些有效。我看了很多文檔,但我還沒有找到我的“啊哈”時刻。
有了這個說......
我正在嘗試動態地將GroupBy表達式添加到我的Linq表達式中。我在這里關注了這個問題: 需要幫助創建Linq.Expression到Enumerable.GroupBy
並試圖實現我在那裡看到的。
首先,我有我的數據庫的實體類,以及一個名為ObjCurLocViewNormalized的表
我有一個方法可以進行初始調用,
public IQueryable<ObjCurLocViewNormalized> getLocations()
{
IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized
select loc);
return res;
}
所以我可以致電:
IQueryable<MetAmericanLinqDataModel.ObjCurLocViewNormalized> locations = american.getLocations();
到目前為止沒問題。
現在,我希望按任意列分組,調用如下:
var grouped = locations.addGroupBy(childLocationFieldName);
現在,我有一個方法:
static public System.Linq.IQueryable<System.Linq.IGrouping<string, TResult>> addGroupBy<TResult>(this IQueryable<TResult> query, string columnName)
{
var providerType = query.Provider.GetType();
// Find the specific type parameter (the T in IQueryable<T>)
var iqueryableT = providerType.FindInterfaces((ty, obj) => ty.IsGenericType && ty.GetGenericTypeDefinition() == typeof(IQueryable<>), null).FirstOrDefault();
var tableType = iqueryableT.GetGenericArguments()[0];
var tableName = tableType.Name;
var data = Expression.Parameter(iqueryableT, "query");
var arg = Expression.Parameter(tableType, tableName);
var nameProperty = Expression.PropertyOrField(arg, columnName);
var lambda = Expression.Lambda<Func<TResult, string>>(nameProperty, arg);
var expression = Expression.Call(typeof(Enumerable),
"GroupBy",
new Type[] { tableType, typeof(string) },
data,
lambda);
var predicate = Expression.Lambda<Func<TResult, String>>(expression, arg); // this is the line that produces the error I describe below
var result = query.GroupBy(predicate).AsQueryable();
return result;
}
所有這些編譯好了,但是當我運行它時,我得到錯誤:
System.ArgumentException: Expression of type 'System.Collections.Generic.IEnumerable`1[System.Linq.IGrouping`2[System.String,MetAmericanLinqDataModel.ObjCurLocViewNormalized]]' cannot be used for return type 'System.String'
並且錯誤來自這一行:
var predicate = Expression.Lambda<Func<TResult, String>>(expression, arg);
我正在復制和調整這段代碼,這是我在動態添加Where子句到表達式時所做的成功工作。所以我有點在黑暗中刺傷。
如果那裡的任何人可以幫助闡明這一點,顯然發布完整的工作代碼並為我做我所有的想法將是偉大的:),但如果你可以只是列出為什麼這是錯的,或如何包裹我的腦袋圍繞這些概念,這將是偉大的。如果你能指出可以真正幫助彌合lambda表達式基礎和構建動態表達式樹之間差距的文檔,那就太棒了。我的知識顯然有很大漏洞,但我認為這些信息可能對其他人有用。
感謝大家的時間,當然,如果我在其他地方找到答案,我會在這裡發布。
再次感謝。
唐
解決方案應該非常簡單:
public static IQueryable<IGrouping<TColumn, T>> DynamicGroupBy<T, TColumn>(
IQueryable<T> source, string column)
{
PropertyInfo columnProperty = typeof(T).GetProperty(column);
var sourceParm = Expression.Parameter(typeof(T), "x");
var propertyReference = Expression.Property(sourceParm, columnProperty);
var groupBySelector = Expression.Lambda<Func<T, TColumn>>(propertyReference, sourceParm);
return source.GroupBy(groupBySelector);
}
假設像這樣的示例類:
public class TestClass
{
public string TestProperty { get; set; }
}
你這樣調用它:
var list = new List<TestClass>();
var queryable = list.AsQueryable();
DynamicGroupBy<TestClass, string>(queryable, "TestProperty");