2017-09-15 36 views
1

假設我有到其中的相關性,且一些參數注入像下面這樣的函數:我怎樣才能斷言參數綁定會成功,沒有副作用?

function Invoke-ACommandLaterOn 
{ 
    param 
    (
     # ... 
     [string] $CommandName, 
     [object] $PipelineParams, 
     [object[]] $PositionalParams, 
     [hashtable]$NamedParams 
     # ... 
    ) 

    Assert-ParameterBinding @PSBoundParameters 
    # ... 
    # Some complicated long-running call tree that eventually invokes 
    # something like 
    # $PipelineParams | & $CommandName @PositionalParams @NamedParams 
    # ... 
} 

我想馬上斷言,到$CommandName參數綁定成功。這就是Assert-ParameterBinding的意思。但是,我不確定如何實施Assert-ParameterBinding

當然我可以嘗試立即調用$CommandName,但在這種情況下,這樣做會產生副作用,直到其他一些長時間運行的東西首先完成纔會發生。

我怎樣才能斷言參數綁定到一個函數將成功,而無需調用該函數?

+0

你的問題不是很清楚。爲什麼不使用'[Parameter()]'驗證屬性? – TheIncorrigible1

+0

「$ CommandName」後面的命令總是由你定義的嗎?該目標是否可以修改? – briantist

+0

@briantist編號'$ CommandName'可以是任何命令。在我的情況下,它是混合了諸如「New-Item」和自定義命令之類的常用命令。 – alx9r

回答

1

如果你做了這樣的事情(在Assert-函數內):

$cmd = Get-Command $CommandName 
$meta = [System.Management.Automation.CommandMetadata]::new($cmd) 
$proxy = [System.Management.Automation.ProxyCommand]::Create($meta) 

$code = $proxy -ireplace '(?sm)(?:begin|process|end)\s*\{.*','begin{}process{}end{}' 

$sb = [scriptblock]::Create($code) 

$PipeLineParams | & $sb @PositionalParams @NamedParams 

實際上,我不知道這是否會與位置PARAMS或潑灑兩套不同的工作,關閉頂部我的頭(我沒有做太多的測試)。

說明

我有幾點想法。首先,參數綁定可能非常複雜。而在管道調用的情況下,綁定發生的方式不同,因爲不同的塊被擊中。

因此,讓PowerShell處理這個問題可能是一個好主意,它基本上是重新創建了相同的函數,但是一個不執行任何操作的主體。

因此,我採用內置的方式生成代理函數,因爲它處理所有這些雜亂的工作,然後殘酷地取代了機體,從而實際上並沒有調用原文。

那麼理想情況下,您將進行所有常規參數綁定過程之後的調用,但最終不會做任何事情。

try/catch中包裝或以其他方式測試錯誤應該是測試這是否成功的呼叫的相當好的測試。

這甚至可以處理動態參數。

有可能是邊緣情況下,這不會工作,但我認爲他們將是罕見的。

另外,ValidateScript屬性和動態參數可能會產生副作用。

+0

謝謝你的建議。我會修補這個概念。我同意最好讓PowerShell嘗試執行綁定。 – alx9r

+0

@ alx9r我貼的代碼絕對需要工作,但我認爲這個概念很有用。好奇你會以任何一種方式結束! – briantist

+1

您可能對@nohwnd和我一直在努力的[本實驗](https://github.com/nohwnd/Mock)感興趣。 – alx9r