[英]Pass Lambda expression to generic repository
我正在嘗試將Web Grid Helper與通用存儲庫結合使用以添加列排序。 帶有網格幫助器的視圖的操作結果具有用於排序列(字符串)的參數。 在我的通用方法簽名中,我需要根據域模型的屬性名稱傳入一個lambda表達式(請參見下文)。
public IEnumerable<T>GetAllPagingAndSorting<TKey>(out int totalRecords,
int pageSize, int pageIndex, Expression<Func<T, TKey>> orderingKey,
SortDirection sortOrder,
params Expression<Func<T, object>>[] includes)
{}
因此,例如,我想將屬性名稱“名稱”和類型“字符串”映射到m => m.Name。
我嘗試按以下方式使用字典,但由於類型現在是對象而不是int,string等,因此調用存儲庫方法時會引發錯誤....
private IDictionary<string,Expression<Func<MyModel,object>>> _orderings =
new Dictionary<string, Expression<Func<MyModel,object>>>
{
{"Id",(m=>m.Id)},
{"Name",m=>m.UserName},
{"DateRequired",m=>m.DateRequired},
{"AssignedTo",m=>m.TeamMember.MemberName},
{"RequestedBy",m=>m.RequestedBy},
};
我應該改用一種方法嗎? 無論哪種情況,我如何使用上面的方法來匹配輸入屬性並返回具有正確類型的Lambda表達式?
更新:這是我在控制器中的操作。...在我使用通用存儲庫時,我想嘗試以Lambda的形式獲取訂購密鑰。
定義的通用資源管理方法:IEnumerable GetAllPagingAndSorting(out int totalRecords,int pageSize,int pageIndex,Expression> orderingKey,SortDirection sortOrder,params Expression> []包括);
public ActionResult ServerPagingAndSorting(int page = 1, string sort = "Id", string sortDir = "Ascending")
{
int totalRecords;
var viewModel =new SupportRequestsIndexVM(supportrequestRepository.GetAllPagingAndSorting(out totalRecords, PageSize,page - 1,_orderings[sort] ,GetSortDirection(sortDir),(m=>m.TeamMember)))
{PageSize = PageSize, PageNumber = page, TotalRows = totalRecords};
return View(viewModel);
}
問題在於類型為Expresion<Func<MyModel, int>>
的表達式(m=>m.Id)
將自動接收對object
的附加Expresion<Func<MyModel, object>>
以匹配Expresion<Func<MyModel, object>>
。 您沒有在代碼中看到強制轉換,但是可以通過分析“表達式樹”來觀察它。
我的方法是
因此我的解決方案看起來像這樣
public class QueryResult<T> {
public int TotalRecords;
public List<T> Records;
}
public QueryResult<T> GetRecords<T>(QueryParams p)
{
IEnumerable<T> q = BuildQueryWithConditions<T>(p);
var result = new QueryResult<T> { TotalRecords = q.Count() };
q = ApplySortOrder(p);
q = ApplyPaging(p);
result.Records = q.ToList();
return result;
}
ApplySortOrder是一個針對每個實體的函數,用於解釋SortColumn和SortOrder:
switch (p.SortColumn)
{
case "Column1":
if (desc)
queryDef = queryDef.OrderByDescending(record => record.Column1);
else
queryDef = queryDef.OrderBy(record => record.Column1);
break;
....
}
要處理每個實體的排序,您需要將IEnumerable<T>
傳遞給函數並返回IOrderedEnumerable<T>
。 由於我們無法在涵蓋不同實體的字典中使用泛型類型,因此簽名如下所示:
Dictionary<Type, Expression<Func<IEnumerable, IEnumerable>>>
另外定義一個方法Add<T>(Expression<Func<IEnumerable<T>, IOrderedEnumerable<T>>>)
添加到字典中,並定義Get()
檢索排序表達式。
我現在正在使用此代碼來應用從另一個堆棧溢出q進行的排序。 我將字符串傳遞給通用存儲庫,然后按以下方式調用此方法:
這是我的存儲庫方法:
public IEnumerable<T> GetAllPagingAndSorting(out int totalRecords, int pageSize, int pageIndex, string orderingKey, string sortDir, params Expression<Func<T, object>>[] includes)
{
IQueryable<T> results = Entities;
totalRecords = results.Count();
// apply any includes
if (includes != null)
{
results = includes.Aggregate(results, (current, include) => current.Include(include));
}
// apply sorting
results = GetSortDirection(sortDir) == SortDirection.Ascending ? ApplyOrder(results, orderingKey, ORDERBY) : ApplyOrder(results, orderingKey, ORDERBYDESC);
if (pageSize > 0 && pageIndex >= 0)
{
// apply paging
results = results.Skip(pageIndex * pageSize).Take(pageSize);
}
return results.ToList();
}
protected static IOrderedQueryable<T> ApplyOrder(IQueryable<T> source, string property, string methodName)
{
string[] props = property.Split('.');
Type type = typeof(T);
ParameterExpression arg = Expression.Parameter(type, "m");
Expression expr = arg;
foreach (string prop in props)
{
// use reflection (not ComponentModel) to mirror LINQ
PropertyInfo pi = type.GetProperty(prop);
expr = Expression.Property(expr, pi);
type = pi.PropertyType;
}
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
object result = typeof(Queryable).GetMethods().Single(
method => method.Name == methodName
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), type)
.Invoke(null, new object[] { source, lambda });
return (IOrderedQueryable<T>)result;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.