我有一个开发场景,我正在使用 Linq 加入两个集合;包含表示元数据的列标题对象的单个列表,以及由 Web 服务调用产生的 kv 字典的枚举。我目前可以for
通过字典枚举迭代 (),并将单个标题列表加入当前的 kv 字典而不会出现问题。加入后,我为每次迭代发出一个精选的字典值数组。
我想做的是消除for
循环,并将单个标题列表直接加入整个枚举。我非常了解 1 对 1 集合连接,但 1 对 N 语法让我难以理解。
细节
我有以下工作方法:
public void GetQueryResults(DataTable outputTable)
{
var odClient = new ODataClient(UrlBase);
var odResponse = odClient.FindEntries(CommandText);
foreach (var row in odResponse)
{
var rowValues = OutputFields
.Join(row, h => h.Key, r => r.Key,
(h, r) => new { Header = h, ResultRow = r })
.Select(r => r.ResultRow.Value);
outputTable.Rows.Add(rowValues.ToArray());
}
}
odResponse
包含IEnumerable<IDictionary<string, object>>
;OutputFields
包含IList<QueryField>
;.Join
生成包含匹配字段元数据 ( .Header
) 和响应 kv 对 ( )的匿名枚举.ResultRow
;最后,.Select
为行消费发出匹配的响应值。该OutputField
集合如下所示:
class QueryField
{
public string Key { get; set; }
public string Label { get; set; }
public int Order { get; set; }
}
声明为:
public IList<QueryField> OutputFields { get; private set; }
通过将字段标题集合连接到响应行,我可以从响应中只提取我需要的列。如果标题键包含 { "size", "shape", "color" } 并且响应键包含 { "size", "mass", "color", "longitude", "latitude" },我将得到一个数组{ "size", "shape", "color" } 的值,其中shape为空,而mass、longitude和latitude值被忽略。对于这种情况,我不关心排序。这一切都是一种享受。
问题
我想做的是重构此方法以返回值数组行的枚举,并让调用者管理数据的使用:
public IEnumerable<string[]> GetQueryResults()
{
var odClient = new ODataClient(UrlBase);
var odResponse = odClient.FindEntries(CommandText);
var responseRows = //join OutputFields to each row in odResponse by .Key
return responseRows;
}
后续问题
用于此重构的 Linq 实现的解决方案是否需要立即扫描枚举,或者它是否可以传回惰性结果?重构的目的是在不引起冗余集合扫描的情况下改进封装。我总是可以构建命令式循环以艰难的方式重新格式化响应数据,但我希望 Linq 提供的是类似于闭包的东西。
非常感谢您花时间阅读本文;任何建议表示赞赏!