Powershell Get命令-使用动态参数时,语法仅返回第一组参数

Powershell Get命令-使用动态参数时,语法仅返回第一组参数,powershell,Powershell,我很难理解Powershell在使用动态参数时如何解析语法 一个简单、可重复的示例: using System; using System.Management.Automation; namespace SOQuestion { [Cmdlet(VerbsCommon.Get, "Greeting")] public class GetGreeting : PSCmdlet, IDynamicParameters { [Parame

我很难理解Powershell在使用动态参数时如何解析语法

一个简单、可重复的示例:

using System;
using System.Management.Automation;

namespace SOQuestion
{
    [Cmdlet(VerbsCommon.Get, "Greeting")]
    public class GetGreeting : PSCmdlet, IDynamicParameters
    {
        [Parameter(Position = 0, Mandatory = true)]
        public NameType NameType { get; set; }

        private object context;
        public object GetDynamicParameters()
        {
            switch (NameType)
            {
                case NameType.First:
                    context =  new DynParamsFirst();
                    return context;
                case NameType.Full:
                    context = new DynParamsFull();
                    return context;
                default:
                    throw new ArgumentException("Invalid type specified");
            }
        }
        protected override void ProcessRecord()
        {
            string name;
            switch (NameType)
            {
                case NameType.First:
                    DynParamsFirst first = context as DynParamsFirst;
                    name = first.FirstName;
                    break;
                case NameType.Full:
                    DynParamsFull full = context as DynParamsFull;
                    name = full.First + " " + full.Last;
                    break;
                default:
                    throw new ArgumentException("Invalid type specified");
            }
            WriteObject($"Hello {name}!");
        }
    }

    public enum NameType
    {
        First = 0,
        Full = 1
    }

    public class DynParamsFirst
    {
        [Parameter(Position = 1, Mandatory = true)]
        public string FirstName { get; set; }
    }

    public class DynParamsFull
    {
        [Parameter(Position = 1, Mandatory = true)]
        public string First { get; set; }
        [Parameter(Position = 2, Mandatory = true)]
        public string Last { get; set; }
    }
}
当在CLI中提供参数时,这将按预期运行,我的参数是动态的,并且我得到了预期的输出

但是当我运行
Get命令Get Greeting-syntax
时,我得到:

获取问候语[-NameType][-FirstName][]

这些是属于
DynParamsFirst
的参数。没有迹象表明参数是动态的。我发现正在拉取的语法是
NameType
enum中第一个匹配的语法-如果我在
NameType
enum中将
Full
设置为
0
,那么
Get命令Get Greeting-syntax
将输出
DynParamsFull
的参数。另外,最有可能是相关的,如果我在没有参数的情况下输入
Get Greeting
,然后按enter键,我总是只会得到
FirstName
,这将与
完整的
名称类型组合抛出一个错误

我觉得这很令人惊讶,而且很难对命令进行记录。我还发现,提出一个恰当的问题并非小事


下面是:如何更改代码,以便在不带参数的情况下输入命令时,Powershell会意识到涉及到动态参数?

-NameType
是cmdlet唯一的静态参数。它的默认值是隐式
[NameType]::new()
,即
[NameType]
类型的隐式默认值:作为
枚举
-派生类型,即作为.NET值类型,它隐式具有一个默认构造函数,该构造函数将值初始化为全零,在您的情况下,该构造函数将转换为
名称类型。首先

因此,如果没有(隐含的)附加上下文,
Get命令Get Greeting-Syntax
的行为就像您将
-NameType First
传递给
Get Greeting
,这就是您看到的语法图:它显示了相应的
-FirstName
动态参数:

PS>Get命令Get Greeting-syntax#暗示:-Args'-NameType',First-见下文。
获取问候语[-NameType][-FirstName][]
为了查看其他语法图可能适用于何种情况,您必须通过其
-ArgumentList
/
-arguments
参数将参数传递给
Get Command-syntax
,该参数随后显示了适当的语法,就好像这些参数被传递给了目标命令一样,
获取问候语

PS>Get命令Get Greeting-syntax-Args'-NameType',完整
获取问候语[-NameType][First][Last][]

请注意,可能需要引用
-NameType
,以免它被解释为另一个参数名,而不是传递给
-Args
-请参见。

查看cmdlet向您显示的内容<代码>示例2:跟踪ParameterBinding操作的操作极好的解释和一个有用的注释,我不知道如何查看其他动态参数集。需要指出的是-如果您不想显示动态参数,除非特别定义了一个值,那么在检查NameType的值之前,请检查if
MyInvocation.BoundParameters.ContainsKey(nameof(NameType))
-这将告诉您用户是否指定了一个
NameType
,而不是默认值(NameType),而不使用可为空的
(因此对最终用户更清楚)。非常有用,谢谢。从可发现性的角度来看,您是否认为上述实现的设计很差?@Rno,可发现性确实很棘手。典型的用例是动态参数取决于提供程序上下文,其中当前位置(
$PWD
)隐式地提供上下文并自动显示动态参数。这就是为什么当当前位置是文件系统位置时,
Get ChildItem-?
显示由
文件系统
提供程序添加的动态
-目录
参数(这是典型的)@Rno,在您的情况下,也许更好的方法是只使用静态参数,并简单地将
-Last
设置为可选。一般来说,可以帮助您实现不同的(静态)参数集参数组合,因此您可以将
Get Greeting-FirstName
作为一个集合,并将
Get Greeting-First-Last
作为另一个集合。@mklement0谢谢您的输入,它非常有启发性。FWIW我通过为每个枚举值创建开关参数来模拟参数集的动态方法。这在技术上是虽然-syntax参数很好地输出了它,但它比“undiscoverable”语法更容易混淆UX。它还存在另一个问题:我无法充分利用
IArgumentCompleter
。但我现在离题了。再次感谢。