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);
    }

}