gpt4 book ai didi

powershell - PowerShell 中的 LINQ

转载 作者:行者123 更新时间:2023-12-05 02:35:25 25 4
gpt4 key购买 nike

我正在将应用程序从 C# 转换为 PowerShell。如何从 PowerShell 调用 LINQ?



[Data.DataTable]$dt = New-Object System.Data.DataTable
[Data.DataColumn]$column = New-Object System.Data.DataColumn "Id", ([int])
$dt.Columns.Add($column)

# add data
[Data.DataRow]$row = $dt.NewRow() #
$row["Id"] = 1
$dt.Rows.Add($row)
$row = $dt.NewRow() #
$row["Id"] = 2
$dt.Rows.Add($row)

# LINQ in C#: int[] results = dt.AsEnumerable().Select(d => d.Field("Id")).ToArray();
[int[]]$results = [Linq.Enumerable]::Select($dt,[Func[int,int]]{ $args[0]})
# Error: Cannot find an overload for "Select" and the argument count: "2"
Write-Host $results

最佳答案

注意:有关从 PowerShell 使用 LINQ 的限制的一般信息,请参阅 this post


问题是 System.Linq.Enumerable.Select() 是一个通用方法,PowerShell 没有办法为所需的类型参数指定类型,至少从 PowerShell 7.2 开始。要使其正常工作,必须使用反射,这非常麻烦(请参阅底部部分)。

但是,您可以改用方便的 PowerShell 功能:member-access enumeration 允许您直接在集合(可枚举)上访问感兴趣的属性,PowerShell 将返回每个元素的属性值:

[int[]] $results = $dt.Id  # same as: $dt.Rows.Id
$results # print -> array 1, 2

$dt.Id 实际上等同于:$dt | ForEach 对象 { $_.Id }


为了完整起见(对于这个用例不值得这样做),这里是基于反射的 LINQ 方法:

注意:

  • PowerShell (Core) 7.3+ 现在支持类似于 C# 的语法,您可以在其中显式指定泛型方法的类型参数 - 请参阅概念 about_Calling_Generic_Methods帮助主题。因此,只有 PowerShell (Core) 7.2 和 Windows PowerShell 才需要下面繁琐的基于反射的方法。
# Using reflection, get the open definition of the relevant overload of the 
# static [Linq.Enumerable]::Select() method.
# ("Open" means: its generic type parameters aren't yet bound, i.e. aren't
# yet instantiated with concrete types.)
$selectMethod = [Linq.Enumerable].GetMethods().Where({
$_.Name -eq 'Select' -and $_.GetParameters()[-1].ParameterType.Name -eq 'Func`2'
}, 'First')

# Close the method with the types at hand and invoke it via reflection.
[int[]] $results = $selectMethod.MakeGenericMethod([Data.DataRow], [int]).Invoke(
# No instance to operate on - the method is static.
$null,
# The arguments for the method, as an array.
(
[Data.DataRow[]] $dt.Rows,
[Func[Data.DataRow,int]] { $args[0].Id }
)
)

# Output the result.
$results

请注意,上面仅显示了如何实例化通用 .Select() 方法。

要获取 [System.Collections.Generic.IEnumerable`1[System.Data.DataRow]] 实例,非惰性 array 转换( [System.Data.DataRow[]]) 用于代替使用 System.Linq.Enumerable.AsEnumerable() - 使用后者也需要使用基于反射的方法。

从上面可以明显看出,从 PowerShell 使用 LINQ 非常麻烦,至少从 v7.2 开始 - GitHub issue #2226 建议在未来引入更好的 LINQ 集成。

对于使用动态(间接)指定数据类型而不是数据类型文字泛化> 例如 [int],请参阅后续问题的 this answer

关于powershell - PowerShell 中的 LINQ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70568993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com