C# 在方法参数中包含OrderBy委托
我有一个方法C# 在方法参数中包含OrderBy委托,c#,lambda,C#,Lambda,我有一个方法 public List<Task> GetTasksByAssignedTo(Guid contactId) { List<Task> tasks = dc.Tasks.Where(x => x.ContactId == contactId).ToList(); return tasks; } 公共列表GetTaskByAssignedTo(Guid联系人ID) { List tasks=dc.
public List<Task> GetTasksByAssignedTo(Guid contactId)
{
List<Task> tasks = dc.Tasks.Where(x => x.ContactId == contactId).ToList();
return tasks;
}
公共列表GetTaskByAssignedTo(Guid联系人ID)
{
List tasks=dc.tasks.Where(x=>x.ContactId==ContactId.ToList();
返回任务;
}
它返回一个项目列表。假设我现在想指定要返回列表的排序顺序
因此,我可能会按姓名、截止日期、完成日期等进行排序
如何将其作为参数包含在方法中?我不想使用switch语句,而是希望尽可能使用lambda
所以,
List-List=GetTasksByAssignedTo(“guid”);
或者这是错误的方法。您可以将
Func
传递给您的订购方法:
public List<Task> GetTasksByAssignedTo(Guid contactId, Func<Task, object> someOrder)
{
List<Task> tasks = dc.Tasks.Where(x => x.ContactId == contactId)
.OrderBy(someOrder)
.ToList();
return tasks;
}
公共列表GetTaskByAssignedTo(Guid contactId,Func someOrder)
{
列出任务=dc.tasks.Where(x=>x.ContactId==ContactId)
.OrderBy(someOrder)
.ToList();
返回任务;
}
现在您可以像这样调用您的方法
Func<Task, object> someOrder = (Task t) => t.DueDate;
List<Task> list = GetTasksByAssignedTo(someGuid, someOrder);
Func someOrder=(任务t)=>t.DueDate;
List List=GetTasksByAssignedTo(someGuid,someOrder);
不过,我大体上同意这些评论——对于一个名为
GetTasksByAssignedTo
@BrokenGlass的方法,似乎不需要排序
另一个选项是使用扩展方法隐藏开关,并将不同的排序选项表示为枚举
public static IEnumerable<Task> WithOrdering(this IEnumerable<Task> source, TaskOrdering order)
{
switch (order)
{
case TaskOrdering.Name:
return source.OrderBy(task => task.Name);
case TaskOrdering.DueDate:
return source.OrderByDescending(task => task.DueDate);
}
}
公共静态IEnumerable with ordering(此IEnumerable源,任务排序顺序)
{
开关(命令)
{
案例任务排序。名称:
返回source.OrderBy(task=>task.Name);
案例TaskOrdering.DueDate:
返回source.OrderByDescending(task=>task.DueDate);
}
}
然后:
public List<Task> GetTasksByAssignedTo(Guid contactId, TaskOrdering order)
{
List<Task> tasks = dc.Tasks.Where(x => x.ContactId == contactId)
.WithOrdering(order)
.ToList();
return tasks;
}
公共列表GetTaskByAssignedTo(Guid联系人ID,任务排序顺序)
{
列出任务=dc.tasks.Where(x=>x.ContactId==ContactId)
.带订单(订单)
.ToList();
返回任务;
}
我总是这样做。允许谓词作为方法参数可能很棘手,因为如果要执行升序/降序,会发生什么?您需要另一个参数(bool),然后执行if/else检查以执行OrderBy
或OrderByDescending
将逻辑隐藏在过滤器中,然后您可以在应用程序中的任何位置重复使用它。我认为您使用LINQ的方法是错误的
public static class TaskEx
{
public static IQueryable<Task> WhereAssignedTo(this IQueryable<Task> tasks,
Guid contactId)
{
return tasks.Where(t => t.ContactId == contactId);
}
public static IQueryable<Task> OrderByName(this IQueryable<Task> tasks)
{
return tasks.OrderBy(t => t.Name);
}
}
LINQ使用延迟执行模型是有原因的。它允许您将一系列操作链接在一起,这些操作只有在您告诉它计算结果时才会执行-通常使用.ToList()
,.ToArray()
,.First()
-但是您也可以通过使用Func
作为参数的OrderBy
子句进行过滤来强制计算
现在,您将返回一个列表
,这意味着您已强制执行-这是准备好使用结果时正确的操作-但如果您继续执行进一步的操作,则可能会将更多记录加载到内存中,而不是您需要的记录
你当然可以这样做:
public List<Task> GetTasksByAssignedTo<P>(Guid contactId, Func<Task, P> orderBy)
{
return dc.Tasks
.Where(x => x.ContactId == contactId)
.OrderBy(orderBy) // this forces evaluation - sort happens in memory
.ToList();
}
因为您的getTaskByAssignedTo
将记录带入内存,所以您正在内存中进行连接。(是的,这个查询有点做作,但原则是可靠的。)
在数据库中执行通常要好得多
以下是修复方法:
public IQueryable<Task> GetTasksByAssignedTo<P>(
Guid contactId,
Expression<Func<Task, P>> orderBy)
{
return dc.Tasks
.Where(x => x.ContactId == contactId)
.OrderBy(orderBy);
}
第一个查询,tasks1
还不错,但它没有告诉您返回类型是什么
第二个查询,tasks2
对一些t
和属性Name
执行了一些操作,但没有告诉您是什么
第三个查询,tasks3
提示它正在按降序排序,但不会告诉您是通过神秘的Name
属性还是其他什么
第四个查询,tasks4
告诉您需要知道的一切-它通过ContactId
过滤任务,通过Name
对结果进行反向排序,最后返回一个列表
现在,看看这个查询:
var query2 =
from t1 in dc.Tasks
where t1.ContactId == contactId
join t2 in dc.Tasks on t1.Name equals t2.Name
where t2.ContactId != contactId
orderby t2.Name descending
select t2;
我可以很容易地读到它,并看到它在做什么。想象一下,对于这个方法,助手方法的名称是什么!或者需要什么疯狂的助手方法嵌套
底线是LINQ是用于查询的API。
如果您非常想创建助手方法,请使用扩展方法
public static class TaskEx
{
public static IQueryable<Task> WhereAssignedTo(this IQueryable<Task> tasks,
Guid contactId)
{
return tasks.Where(t => t.ContactId == contactId);
}
public static IQueryable<Task> OrderByName(this IQueryable<Task> tasks)
{
return tasks.OrderBy(t => t.Name);
}
}
这就是清晰、简洁、可扩展、可组合、可重用,并且您可以控制何时执行。。。输入参数为字符串形式。这是根据StackOverflow修改的解决方案
public static class TaskEx
{
public static IQueryable<Task> WhereAssignedTo(this IQueryable<Task> tasks,
Guid contactId)
{
return tasks.Where(t => t.ContactId == contactId);
}
public static IQueryable<Task> OrderByName(this IQueryable<Task> tasks)
{
return tasks.OrderBy(t => t.Name);
}
}
/// <summary>
/// Sort List<typeparam name="T"></typeparam> objects base on string options
/// </summary>
/// <param name="SortDirection">Ascending or Descending</param>
/// <param name="ColumnName">Column name in complex object (object.ColumnName)</param>
public static class ListExtension
{
public static List<T> SortList<T>(this List<T> data, string sortDirection, string sortExpression)
{
try
{
switch (sortDirection)
{
case "Ascending":
data = (from n in data
orderby GetDynamicSortProperty(n, sortExpression) ascending
select n).ToList();
break;
case "Descending":
data = (from n in data
orderby GetDynamicSortProperty(n, sortExpression) descending
select n).ToList();
break;
default:
data = null; //NUL IF IS NO OPTION FOUND (Ascending or Descending)
break;
}
return data;
} catch(Exception ex){
throw new Exception("Unable to sort data", ex);
}
}
private static object GetDynamicSortProperty(object item, string propName)
{
//Use reflection to get order type
return item.GetType().GetProperty(propName).GetValue(item, null);
}
}
//
///基于字符串选项对列表对象进行排序
///
///上升或下降
///复杂对象中的列名(object.ColumnName)
公共静态类ListExtension
{
公共静态列表排序列表(此列表数据、字符串排序方向、字符串排序表达式)
{
尝试
{
开关(排序方向)
{
案例“升序”:
数据=(从数据中的n开始)
orderby GetDynamicPortProperty(n,sortExpression)升序
选择n.ToList();
打破
案例“下降”:
数据=(从数据中的n开始)
orderby GetDynamicPortProperty(n,sortExpression)降序
选择n.ToList();
打破
违约:
data=null;//如果未找到选项(升序或降序),则为NUL
打破
}
返回数据;
}捕获(例外情况除外){
抛出新异常(“无法对数据进行排序”,例如);
}
}
私有静态对象GetDyna
public static class TaskEx
{
public static IQueryable<Task> WhereAssignedTo(this IQueryable<Task> tasks,
Guid contactId)
{
return tasks.Where(t => t.ContactId == contactId);
}
public static IQueryable<Task> OrderByName(this IQueryable<Task> tasks)
{
return tasks.OrderBy(t => t.Name);
}
}
var tasks = dc.Tasks
.WhereAssignedTo(contactId)
.OrderByName()
.ToList();
/// <summary>
/// Sort List<typeparam name="T"></typeparam> objects base on string options
/// </summary>
/// <param name="SortDirection">Ascending or Descending</param>
/// <param name="ColumnName">Column name in complex object (object.ColumnName)</param>
public static class ListExtension
{
public static List<T> SortList<T>(this List<T> data, string sortDirection, string sortExpression)
{
try
{
switch (sortDirection)
{
case "Ascending":
data = (from n in data
orderby GetDynamicSortProperty(n, sortExpression) ascending
select n).ToList();
break;
case "Descending":
data = (from n in data
orderby GetDynamicSortProperty(n, sortExpression) descending
select n).ToList();
break;
default:
data = null; //NUL IF IS NO OPTION FOUND (Ascending or Descending)
break;
}
return data;
} catch(Exception ex){
throw new Exception("Unable to sort data", ex);
}
}
private static object GetDynamicSortProperty(object item, string propName)
{
//Use reflection to get order type
return item.GetType().GetProperty(propName).GetValue(item, null);
}
}