我可以将两个参数传递给管道吗?

时间:2018-11-28 14:58:59

标签: powershell

我用C#编写了一个PowerShell cmdlet,该cmdlet最初采用了几个参数,但只接受了管道输入中的一个。我将其他参数压缩为单个自定义C#对象,我希望将其作为管道的输入。这是相关代码:

[Parameter(ValueFromPipeline = true, Mandatory = true)]
public DataObj Data {get; set;}

[Parameter(ValueFromPipeline = true, Mandatory = false)]
public DataSettings Settings {get; set;} = new DataSettings();

public class DataObj {
     public string Name {get; set;}
     public int Value {get; set;}
     ...
}

public class DataSettings {
    public DataInfo Info {get; set;} = new DataInfo();
    public string Description {get; set} = "";
}

在将其修改为管道输入之前,我已经能够从PowerShell中的DataSettings成功创建HashTable对象。

我尝试过:

@{Data = $DataObj; Settings = $DataSettings;} | Add-Data

以及:

$DataObj $DataSettings | Add-Data

从我对PowerShell参数绑定的了解来看,管道输入将绑定到可以转换为该参数的参数。在我的PowerShell脚本中,$DataSettings$DataObj都是包含相关属性的HashTable

当我在PowerShell脚本中运行以上任一行时,出现“输入对象无法绑定到任何参数...”错误。

是否可以通过这种方式从管道中获取两个输入?我曾考虑过创建一个自定义C#对象来封装两个输入对象,但是我一直试图将强制性部分与不需要的部分分开。

此外,我尝试运行Trace-Command,但尝试之后:

Trace-Command ParameterBinding {Add-Data $Input} -PSHost -InputObject @{Data = $DataObj; Settings = $DataSettings;}

我收到一个错误,提示没有参数与名称Data相匹配。我试图遵循此tutorial,但显然我做错了事。

1 个答案:

答案 0 :(得分:1)

使用管道时,将输入对象包装到单个对象中是将它们各自绑定到不同参数的唯一方法,为此,您可以使用delay-bind script blocks

@{ Data = $DataObj; Settings = $DataSettings } |
  Add-Data -Data { $_.Data } -Settings { $_.Settings }

独立于管道,您可以使用splatting更优雅地达到相同的效果:

# Construct the arguments to pass as a hashtable.
$htArgs = @{ Data = $DataObj; Settings = $DataSettings }

# Pass the arguments via splatting (note the '@')
Add-Data @htArgs

您可以通过ForEach-Object 组合这两种技术,但是请注意,使用多种输入方式效率较低,因为随后在< em>每次迭代:

Add-Data