在回答我之前的问题时,我得到了一个作业脚本,它基于字面上指定为[int]
.
现在我想动态更改资料型别。是否可以?
uj5u.com热心网友回复:
上一个问题的答案使用型别文字( [...]
),它要求所有型别都逐字指定(通过它们的文字名称)。
- 型别文字不支持变量参考;如
[Func[Data.DataRow, $columnType]]
不不作业-它会导致一个语法错误。
要基于动态确定(间接指定)的型别来概括链接的答案,需要进行两项修改:
您必须通过
.MakeArrayType()
and.MakeGenericType()
方法构造(实体化)LINQ 方法呼叫中涉及的封闭泛型型别。您必须使用
-as
时,有条件的型别转换运算子投输入物件/转换脚本块({ ... }
)这些型别。
# Create a sample data table...
[Data.DataTable] $dt = New-Object System.Data.DataTable
[Data.DataColumn] $column = New-Object System.Data.DataColumn "Id", ([int])
$dt.Columns.Add($column)
# ... and add data.
[Data.DataRow]$row = $dt.NewRow()
$row["Id"] = 1
$dt.Rows.Add($row)
$row = $dt.NewRow()
$row["Id"] = 2
$dt.Rows.Add($row)
# 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')
# Dynamically set the name of the column to use in the projection.
$colName = 'Id'
# Dynamically set the in- and output types to use in the LINQ
# .Select() (projection) operation.
$inType = [Data.DataRow]
$outType = [int]
# Now derive the generic types required for the LINQ .Select() method
# from the types above:
# The array type to serve as the input enumerable.
# Note: As explained in the linked answer, the proper - but more cumbersome -
# solution would be to use reflection to obtain a closed instance of
# the generic .AsEnumerable() method.
$inArrayType = $inType.MakeArrayType()
# The type for the 'selector' argument, i.e. the delegate performing
# the transformation of each input object.
$closedFuncType = [Func`2].MakeGenericType($inType, $outType)
# Close the generic .Select() method with the given types
# and invoke it.
[int[]] $results = $selectMethod.MakeGenericMethod($inType, $outType).Invoke(
# No instance to operate on - the method is static.
$null,
# The arguments for the method, as an array.
# Note the use of the -as operator with the dynamically constructed types.
(
($dt.Rows -as $inArrayType),
({ $args[0].$colName } -as $closedFuncType)
)
)
# Output the result.
$results
退后一步:
如链接答案所示,PowerShell 的成员列举可以提供相同的功能,语法大大简化,无需显式处理型别:
# Create a sample data table...
[Data.DataTable] $dt = New-Object System.Data.DataTable
[Data.DataColumn] $column = New-Object System.Data.DataColumn "Id", ([int])
$dt.Columns.Add($column)
# ... and add data.
[Data.DataRow]$row = $dt.NewRow()
$row["Id"] = 1
$dt.Rows.Add($row)
$row = $dt.NewRow()
$row["Id"] = 2
$dt.Rows.Add($row)
# Dynamically set the name of the column to use in the projection.
$colName = 'Id'
# Use member enumeration to extract the value of the $colName column
# from all rows.
$dt.$colName # Same as: $dt.Rows.$colName
uj5u.com热心网友回复:
您可能想要备份并问自己为什么要尝试在 PowerShell 中使用 LINQ。提示是,如果它看起来像 C#,则可能有更好的方法来做到这一点。
我假设您是 PowerShell 的新手,因此我将简要介绍一下为什么 LINQ 在与管道结合使用时实际上在 PowerShell 中“更容易”(从技术上讲,它不再是 LINQ,但我认为它看起来确实如此)。
Get-Help *-Object
有时尝试使用 PowerShell 提示符。注意到出现的 cmdlet 了吗?Select-Object
, Where-Object
, Group-Object
, 和Sort-Object
执行与 LINQ 相同的操作,并且它们的名称符合您的期望。另外,严格来说没有强型别要求。
$data | Where-Object -Property Greeting -Like *howdy* | Select-Object Name,Year,Greeting
0 评论