我正在撰寫一個函式,它基本上是一個圍繞它將呼叫的外部程式的便利包裝器。一些引數將被轉發到外部程式,但不是全部。
我在寫
$ArgsToFwd = @()
switch ($PSBoundParameters.Keys) {
'--server' {$ArgsToFwd = @('--server',$server)}
'--userid' {$ArgsToFwd = @('--userid',$userid)}
...
}
但后來我認為定義一個自定義引數屬性可能會更好,它可以讓我執行以下操作:
params(
[Parameter()]
[IsExternal()]
[string]$Server
)
#...
foreach ($key in $PSBoundParameters.Keys) {
if (<#a test for the custom [IsExternal] attribute#>) {
$ArgsToFwd = @($key, $PSBoundParameters[$key])
}
}
但我無法完全弄清楚。可以這樣做嗎?
uj5u.com熱心網友回復:
如果你想使用自定義屬性,你需要做 3 件事:
- 定義自定義
Attribute型別 - 用所述屬性的實體裝飾函式的引數
- 撰寫一種機制來發現屬性裝飾并在運行時對其進行處理
讓我們從第 1 步開始,定義一個繼承自的自定義類System.Attribute:
class ProxyParameterAttribute : Attribute
{
[string]$Target
ProxyParameterAttribute([string]$Target){
$this.Target = $Target
}
}
屬性注釋直接映射回目標屬性的建構式,因此在這種情況下,我們將像使用它一樣使用它[ProxyParameter('someValue')],然后'someValue'將其存盤在$Target屬性中。
現在我們可以繼續第 2 步,用新屬性裝飾我們的引數。Attribute在塊中應用名稱時,您可以省略名稱的一部分param,PowerShell期望所有注釋無論如何都與屬性相關:
function Invoke-SomeProgram
{
param(
[ProxyParameter('--server')]
[Parameter()]
[string]$Server
)
# ... code to resolve ProxyParameter goes here ...
}
對于第 3 步,我們需要一段代碼,它可以發現當前命令的引數上的屬性注釋,并使用它們將輸入引數引數映射到適當的目標名稱。
要發現當前命令的宣告引數元資料,最好的入口點是$MyInvocation:
# Create an array to hold all the parameters you want to forward
$argumentsToFwd = @()
# Create mapping table for parameter names
$paramNameMapping = @{}
# Discover current command
$currentCommandInfo = $MyInvocation.MyCommand
# loop through all parameters, populate mapping table with target param names
foreach($param in $currentCommandInfo.Parameters.GetEnumerator()){
# attempt to discover any [ProxyParameter] attribute decorations
$proxyParamAttribute = $param.Value.Attributes.Where({$_.TypeId -eq [ProxyParamAttribute]}, 'First') |Select -First 1
if($proxyParamAttribute){
$paramNameMapping[$param.Name] = $proxyParamAttribute.Target
}
}
# now loop over all parameter arguments that were actually passed by the caller, populate argument array while taking ProxyParameter mapping into account
foreach($boundParam in $PSBoundParameters.GetEnumerator()){
$name = $boundParam.Name
$value = $boundParam.Value
if($paramNameMapping.ContainsKey[$name]){
$argumentsToFwd = $paramNameMapping[$name],$value
}
}
現在引數已被適當地過濾和重命名,您可以通過 splatting 使用正確的引數呼叫目標應用程式:
.\externalApp.exe @argumentsToFwd
把它們放在一起,你最終會得到類似的東西:
class ProxyParameterAttribute : Attribute
{
[string]$Target
ProxyParameterAttribute([string]$Target){
$this.Target = $Target
}
}
function Invoke-SomeProgram
{
param(
[ProxyParameter('--server')]
[Parameter()]
[string]$Server
)
# Create an array to hold all the parameters you want to forward
$argumentsToFwd = @()
# Create mapping table for parameter names
$paramNameMapping = @{}
# Discover current command
$currentCommandInfo = $MyInvocation.MyCommand
# loop through all parameters, populate mapping table with target param names
foreach($param in $currentCommandInfo.Parameters.GetEnumerator()){
# attempt to discover any [ProxyParameter] attribute decorations
$proxyParamAttribute = $param.Value.Attributes.Where({$_.TypeId -eq [ProxyParamAttribute]}, 'First') |Select -First 1
if($proxyParamAttribute){
$paramNameMapping[$param.Name] = $proxyParamAttribute.Target
}
}
# now loop over all parameter arguments that were actually passed by the caller, populate argument array while taking ProxyParameter mapping into account
foreach($boundParam in $PSBoundParameters.GetEnumerator()){
$name = $boundParam.Name
$value = $boundParam.Value
if($paramNameMapping.ContainsKey[$name]){
$argumentsToFwd = $paramNameMapping[$name],$value
}
}
externalApp.exe @argumentsToFwd
}
您可以將其他屬性和建構式引數添加到屬性以存盤更多/不同的資料(例如,指示某物是否只是開關的標志,或轉換輸入值的腳本塊)。
如果您需要對多個不同的命令執行此操作,請將步驟 3 邏輯(發現屬性和決議引數名稱)提取到單獨的函式中,或者將其封裝在屬性類的靜態方法中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/414557.html
標籤:
上一篇:PowerShell使用包含“/”的引數運行系統命令
下一篇:無法連接到Azure檔案共享
