首页 > 解决方案 > 我可以将两个参数传递给管道吗?

问题描述

我用 C# 编写了一个 PowerShell 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} = "";
}

在将其修改为管道输入之前,我已经能够DataSettings从 PowerShell 中成功创建对象。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。我试图按照本教程进行操作,但显然我做错了什么。

标签: powershell

解决方案


当您使用管道时,将输入对象包装到单个对象中是将它们各自绑定到不同参数的唯一方法,为此您可以使用延迟绑定脚本块

@{ 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,但请注意,使用多个输入时效率会降低,因为Add-Data每次迭代中都会进行单独的调用:

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

推荐阅读