擴充 Dynamic LINQ 支援查詢時 回傳指定型別
最近在開發時遇到一個情境,需要動態決定Linq查詢的欄位清單,並回傳到指定的型別。
舉例,不使用Dynamic Linq的寫法
1: List<SourceClass> list = new List<SourceClass>();
2: var result = list.Select(a=>new TargetClass{ Id = a.No, Name = a.FullName);
改用Dynamic Linq 我改成以下寫法
1: List<SourceClass> list = new List<SourceClass>();
2: var result = list.AsQueryable().Select("new TargetClass(No as Id,FullName as Name)");
@@ 很不幸的 ,這樣是不會Work的
回頭Google了一下,然後去追Dynamic Linq 原始檔
修改步驟如下
Step 1 :
開啟Dynamic.cs
Step 2 :
先找到此區塊
1: public Expression Parse(Type resultType)
2: {
3: int exprPos = token.pos;
4: ...
5: return expr;
6: }
修改成
1: private Type tmpResultType; //加入此行,用來暫存resultType
2: public Expression Parse(Type resultType)
3: {
4: tmpResultType = resultType; //加入此行,存入resultType
5: int exprPos = token.pos;
6: ...
7: return expr;
8: }
Step 3 :
找到此區塊
1: private Expression ParseNew()
2: {
3: NextToken();
4: ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
5: ...
6: return Expression.MemberInit(Expression.New(type), bindings);
7: }
修改成
1: private Expression ParseNew()
2: {
3: NextToken();
4: ...
5: NextToken();
6: Type type = tmpResultType ?? DynamicExpression.CreateClass(properties); //修改此行,直接設定要回傳的型別
7: MemberBinding[] bindings = new MemberBinding[properties.Count];
8: for (int i = 0; i < bindings.Length; i++)
9: bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);
10: return Expression.MemberInit(Expression.New(type), bindings);
11: }
Step 4 :
新增此區段
public static IQueryable Select(this IQueryable source, string selector, params object[] values)
{
if (source == null) throw new ArgumentNullException("source");
if (selector == null) throw new ArgumentNullException("selector");
LambdaExpression lambda = System.Linq.Dynamic.DynamicExpression.ParseLambda(source.ElementType, typeof(TResult), selector, values);
return source.Provider.CreateQuery(
Expression.Call(
typeof(Queryable), "Select",
new Type[] { source.ElementType, typeof(TResult) },
source.Expression, Expression.Quote(lambda)));
}
完工
最後使用方式
1: List<SourceClass> list = new List<SourceClass>();
2: var result = list.AsQueryable().Select<TargetClass>("new(No as Id,FullName as Name)");
就可以順利回傳指定型別囉~~~~
參考資料
- 如果您覺得這篇文章有幫助,請您幫忙推薦一下或按上方的"讚"給予支持,非常感激
- 歡迎轉載,但請註明出處
- 文章內容多是自己找資料學習到的心得,如有不詳盡或錯誤的地方,請多多指教,謝謝