从对象集合动态构建 lambda 表达式?

Dynamically build lambda expression from a collection of objects?

我有一个以这种格式存储的排序列表:

public class ReportSort
{
    public ListSortDirection SortDirection { get; set; }
    public string Member { get; set; }
}

并且我需要将其转换为 Action<DataSourceSortDescriptorFactory<TModel>>

类型的 lambda 表达式

所以假设我有以下报告分类集合:

new ReportSort(ListSortDirection.Ascending, "LastName"),
new ReportSort(ListSortDirection.Ascending, "FirstName"),

我需要将其转换成这样的语句才能像这样使用:

.Sort(sort => { 
        sort.Add("LastName").Ascending();
        sort.Add("FirstName").Ascending();
      })

并且排序方法签名是:

public virtual TDataSourceBuilder Sort(Action<DataSourceSortDescriptorFactory<TModel>> configurator)

所以我现在有一些方法:

public static Action<DataSourceSortDescriptorFactory<TModel>> ToGridSortsFromReportSorts<TModel>(List<ReportSort> sorts) where TModel : class
    {
        Action<DataSourceSortDescriptorFactory<TModel>> expression;
        //stuff I don't know how to do
        return expression;
    }

...我不知道在这里做什么。

编辑:答案是:

var expression = new Action<DataSourceSortDescriptorFactory<TModel>>(x =>
        {
            foreach (var sort in sorts)
            {
                if (sort.SortDirection == System.ComponentModel.ListSortDirection.Ascending)
                {
                    x.Add(sort.Member).Ascending();
                }
                else
                {
                    x.Add(sort.Member).Descending();
                }
            }
        });

起初我在想我必须使用表达式 class 从头开始​​动态构建一个 lambda 表达式。幸运的是,情况并非如此。

您可以使用以下可以分配给 Action<T> 委托的 lambda 表达式。在该 lambda 表达式中,捕获 List<T> 变量并对其进行循环:

public static Action<DataSourceSortDescriptorFactory<TModel>> ToGridSortsFromReportSorts<TModel>(List<ReportSort> sorts) where TModel : class
{
    Action<DataSourceSortDescriptorFactory<TModel>> expression = 
       result  => 
       {
           foreach (var sort in sorts)
           {
                if (sort.SortDirection == ListSortDirection.Ascending)
                    result.Add(sort.Member).Ascending();
                else // or whatever other methods you want to handle here
                    result.Add(sort.Member).Descending();
           }
       };
    return expression;
}

...and I have no idea what to do here.

好吧,推理一下。

你手里拿着什么?一个叫 sortsList<ReportSort>

你需要什么?一个Action<Whatever>.

您已经迈出了第一步:您已经创建了一种方法,该方法采用您拥有的东西和 returns 您需要的东西。伟大的第一步。

    Action<DataSourceSortDescriptorFactory<TModel>> expression;
    //stuff I don't know how to do
    return expression;

而且您已经指出了您不知道该怎么做的事情 -- 还没有。这是一个很好的技术。

首先填写一些可以编译但不能正常工作的内容。

Action<DataSourceSortDescriptorFactory<TModel>> expression = 
  sort => {         
    sort.Add("LastName").Ascending();
    sort.Add("FirstName").Ascending();
  };
return expression;

非常好。 现在你有了一个编译程序,这意味着你可以 运行 你的测试并验证如果预期这种情况,测试通过,如果预期有任何其他情况,测试失败。

现在想想,我手里拿的是什么?我有一个清单,我正在做 Action。这意味着副作用正在发生,可能涉及列表中的每一项。所以那里可能有一个 foreach

Action<DataSourceSortDescriptorFactory<TModel>> expression = 
  sort => {         
    sort.Add("LastName").Ascending();
    sort.Add("FirstName").Ascending();
    foreach(var sort in sorts) { 
      // Do something
    }
  };
return expression;

编译它。它失败。啊,我们混淆了我们要添加的种类和我们要添加的新种类。解决问题。

Action<DataSourceSortDescriptorFactory<TModel>> expression = 
  existingSort => {         
    existingSort.Add("LastName").Ascending();
    existingSort.Add("FirstName").Ascending();
    foreach(var newSort in sorts) { 
      // Do something
    }
  };
return expression;

太好了,现在我们又可以编译和 运行 测试了。

这里的模式应该很清楚了。 继续编译,继续运行测试,逐渐让你的程序越来越正确,思考你可以对你手头的值执行的操作。

你能完成吗?