在回答我之前的問題時,我得到了一個作業腳本,它基于字面上指定為[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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/405925.html
標籤:
