C# 在变量中存储具有多个可能输出类型的Lambda表达式

C# 在变量中存储具有多个可能输出类型的Lambda表达式,c#,asp.net-mvc,lambda,C#,Asp.net Mvc,Lambda,问题: 我有一个包含排序按钮的标题的html表。数据在控制器上提取,并根据传递的路由值(字符串)使用OrderBy()进行排序。我目前正在使用一个巨大的switch语句,它需要对每个列进行col\u asc和col\u desc检查,以确定请求的排序方法。我想尽可能地减少这个值,然后添加一个然后再添加一个排序,它也将作为路由值传递 Func<MProduct,int> orderByLambda; switch (orderByColName) { case "asset_d

问题:

我有一个包含排序按钮的标题的html表。数据在控制器上提取,并根据传递的路由值(字符串)使用
OrderBy()
进行排序。我目前正在使用一个巨大的switch语句,它需要对每个列进行
col\u asc
col\u desc
检查,以确定请求的排序方法。我想尽可能地减少这个值,然后添加一个
然后再添加一个
排序,它也将作为路由值传递

Func<MProduct,int> orderByLambda;
switch (orderByColName)
{
    case "asset_desc":
        //models = models.OrderByDescending(m => m.AssetId);
        orderByLambda = m => m.AssetId; // this is test code
        break;
    case "asset_asc":
        models = models.OrderBy(m => m.AssetId);

        break;
    case "location_desc":
        models = models.OrderByDescending(m => m.Locations.Name);
        break;
    case "location_asc":
        models = models.OrderBy(m => m.Locations.Name);
        break;

    ...... So on and so forth ......

    case "manufacturer_desc":
        models = models.OrderByDescending(m => m.Models.Manufacturers.Name);
        break;
    case "manufacturer_asc":
        models = models.OrderBy(m => m.Models.Manufacturers.Name);
        break;
    default:
        models = models.OrderByDescending(m => m.AssetId);
        break;
}
我被困的地方


到目前为止,这似乎是可行的(VisualStudio没有显示任何红色)。但是,由于必须将lambda变量声明为type
Func
,因此无法传递数据类型不是
int
的列。我怎样才能克服这个问题?有更好的办法吗?我正在研究
动态
类型,但我不能100%确定该类型是否有效。

您可以将
顺序
设置为通用,但这意味着调用者需要指定列的类型

private IEnumerable<MProduct> Order<T>(List<MProduct> items, bool isDescending, Func<MProduct, T> orderByLambda)
{
    if (isDescending)
    {
        return items.OrderByDescending(orderByLambda);
    }
    return items.OrderBy(orderByLambda);
}

您可以将
Order
设置为泛型,但这意味着调用者需要指定列的类型

private IEnumerable<MProduct> Order<T>(List<MProduct> items, bool isDescending, Func<MProduct, T> orderByLambda)
{
    if (isDescending)
    {
        return items.OrderByDescending(orderByLambda);
    }
    return items.OrderBy(orderByLambda);
}

这种方法有很多我喜欢的地方,但目前它有点让我不知所措。现在已经很晚了,我晚上没时间了,但我会深入研究,学一两样东西,然后在那一点之后标记为已被接受。谢谢@TylerSells很乐意提供帮助,如果我能提供任何信息,请毫不犹豫地询问:)这种方法有很多我喜欢的地方,但目前我有点不知所措。现在已经很晚了,我晚上没时间了,但我会深入研究,学一两样东西,然后在那一点之后标记为已被接受。谢谢@TylerSells很乐意帮忙,如果我能提供任何信息,请毫不犹豫地询问:)您可以将
Func
更改为
Func
,在您的情况下应该可以正常工作。您可以将
Func
更改为
Func
,在您的情况下应该可以正常工作。
private IEnumerable<MProduct> Order(List<MProduct> items, bool isDescending, Action<IApplyer<MProduct>> orderByLambda)
{
    IApplyer<MProduct> applyer;
    if (isDescending)
    {
        applyer = new OrderByApplyer<MProduct>(items);
    }
    else
    {
        applyer = new OrderDescendingByApplyer<MProduct>(items);
    }
    orderByLambda(applyer);
    return applyer.Result;
}

// Usage
Order(items, true, a => a.Apply(o => o.Name));
Order(items, true, a => a.Apply(o => o.Age));
Dictionary<string, Action<IApplyer<MProduct>>> columns = new Dictionary<string, Action<IApplyer<MProduct>>>
{
    ["Name"] = a => a.Apply(o => o.Name),
    ["Age"] = a => a.Apply(o => o.Age),
};
Order(items, true, columns["Age"]);

//Implementation

interface IApplyer<TTarget>
{
    void Apply<TColumn>(Func<TTarget, TColumn> orderBy);
    IOrderedEnumerable<TTarget> Result { get; }
}

class OrderByApplyer<TTarget> : IApplyer<TTarget>
{
    public OrderByApplyer(IEnumerable<TTarget> target)
    {
        this.Target = target;
    }

    public IEnumerable<TTarget> Target { get; }
    public IOrderedEnumerable<TTarget> Result { get; set; }

    public void Apply<TColumn>(Func<TTarget, TColumn> orderBy)
    {
        this.Result = this.Target.OrderBy(orderBy);
    }
}

class OrderDescendingByApplyer<TTarget> : IApplyer<TTarget>
{
    public OrderDescendingByApplyer(IEnumerable<TTarget> target)
    {
        this.Target = target;
    }

    public IEnumerable<TTarget> Target { get; }
    public IOrderedEnumerable<TTarget> Result { get; set; }

    public void Apply<TColumn>(Func<TTarget, TColumn> orderBy)
    {
        this.Result = this.Target.OrderByDescending(orderBy);
    }
}
class ThenByApplyer<TTarget> : IApplyer<TTarget>
{
    public ThenByApplyer(IOrderedEnumerable<TTarget> target)
    {
        this.Target = target;
    }

    public IOrderedEnumerable<TTarget> Target { get; }
    public IOrderedEnumerable<TTarget> Result { get; set; }

    public void Apply<TColumn>(Func<TTarget, TColumn> orderBy)
    {
        this.Result = this.Target.ThenBy(orderBy);
    }
}

class ThenByDescendingByApplyer<TTarget> : IApplyer<TTarget>
{
    public ThenByDescendingByApplyer(IOrderedEnumerable<TTarget> target)
    {
        this.Target = target;
    }

    public IOrderedEnumerable<TTarget> Target { get; }
    public IOrderedEnumerable<TTarget> Result { get; set; }

    public void Apply<TColumn>(Func<TTarget, TColumn> orderBy)
    {
        this.Result = this.Target.ThenByDescending(orderBy);
    }
}