2015-10-06 33 views
1

我开发C#中的PowerShell命令Get-Foo定义了dynamic parameterBar,应该显示指定开关参数MySwitch只有当不被调用。它也有其他参数MyStringMyIntMyBoolGetDynamicParameters()时指定了其他参数

当我运行cmdlet,动态参数Bar在标签完成时予以任一MyStringMyInt但不是当我使用它与MyBool(或任何其他参数类型)沿着指定开关参数MySwitch显示出来就好了。

下面的代码:

namespace MyCompany.Cmdlets 
{ 
    [Cmdlet(VerbsCommon.Get, "Foo")] 
    public class GetFoo : PSCmdlet, IDynamicParameters 
    { 
     [Parameter] 
     public string MyString { get; set; } 

     [Parameter] 
     public int MyInt { get; set; } 

     [Parameter] 
     public bool MyBool { get; set; } 

     [Parameter] 
     public SwitchParameter MySwitch { get; set; } 

     public object GetDynamicParameters() 
     { 
      if (MySwitch.IsPresent) 
      { 
       context = new FooParameters(); 
       return context; 
      } 

      return null; 
     } 

     private FooParameters context; 

     protected override void ProcessRecord() {} 
    } 

    public class FooParameters 
    { 
     [Parameter] 
     public string Bar { get; set; } 
    } 
} 

我在做什么错?指定MyBool参数(或参数MyObject)时如何获得动态参数?

+0

只是出于好奇:为什么你会指定位置,开关参数?这种类型几乎没有任何意义 - 它是(通过本质)命名参数...不知道这是否会导致动态参数的问题,但我不会感到惊讶。 – BartekB

+0

我认为,PowerShell无法伪装“bool”参数的绑定值。完成解析时,它不评估表达式。例如,如果您编写'-MyString $ a',而不是'GetDynamicParameters',它将被视为'$ a',而不是变量的值。因此,PowerShell可能无法将字符串“$ false”或“$ true”转换为“bool”值。 – PetSerAl

+0

@BartekB这只是我玩弄这个工作的一件事。即使删除所有位置属性后,它也不起作用。 –

回答

1

当使用结构“SwitchParameter”,我把它当作我做任何其他布尔,例如:

if (MySwitchParameter) 
{ 
    // la la la other stuff 
} 

GetDynamicParameters是棘手的,但是,你有它两个选项在返回 价值方面:返回一个代表您的参数的对象返回一个 RuntimeDefinedParameterDictionary对象。将RuntimeDefinedParameterDictionary 想象为表达参数的“CodeDom-Like”方式。

这里是一个可以改写你的GET-富cmdlet时,重点对动态参数:

[Cmdlet(VerbsCommon.Get, "Foo", 
    SupportsShouldProcess = true 
    )] 
public class GetFooCommand : PSCmdlet, IDynamicParameters 
{ 
    // First things first: Lets try making a dictionary for our return 
    // value in our implementation of IDynamicParameter's 
    // GetDynamicParameters() method 
    private RuntimeDefinedParameterDictionary DynamicParameters; 

    [Parameter] 
    public string MyString { get; set; } 

    [Parameter] 
    public int MyInt { get; set; } 

    [Parameter] 
    // Booleans are not as fun as SwitchParameters, IMHO 
    public bool MyBool { get; set; } 


    // Remember that SwitchParameter is really just a boolean (sort of), so 
    // it will default to 'false' 
    [Parameter] 
    public SwitchParameter MySwitch { get; set; } 

    public object GetDynamicParameters() 
    { 
     // You only want this to run when the switch is flipped, 
     // so try it this way and see if it works for you 
     if (MySwitch) 
     { 
      // Create the dictionary. We will return this at the end because 
      // **** spoiler alert **** it is an object :) 
      var runtimeParameterDictionary = new RuntimeDefinedParameterDictionary(); 


      // Lets make that parameter now. Your example doesn't specify any 
      // additional parameter attributes beyond the required "ParameterAttribute", 
      // so here we create an empty Attribute Collection 
      var runtimeParameter = 
      new RuntimeDefinedParameter("Bar", typeof (string), new Collection<Attribute>()); 

      // With a new Parameter, lets add it to our dictionary. 
      runtimeParameterDictionary.Add("Bar", runtimeParameter); 

      // Because we created a field for our dictionary way up top, we can assign it like I 
      // illustrate below. This will enable easy, predictable results when we seek to 
      // extract the values from the dictionary at runtime. 
      DynamicParameters = runtimeParameterDictionary; 


      // Note: You can add as many parameters as you want this way, and that Is 
      // why I recommend it to you now. Coding the parameters as classes outside of the 
      // Cmdlet, and to some extent as embedded Classes, 
      // within the Cmdlet Never really worked for me, so I feel your pain/frustration. 

      return runtimeParameterDictionary; 
     } 

     return null; // Guess the user doesn't want that Bar afterall; 
    } 

    protected override void ProcessRecord() 
    { 
     // We obviously want to sequester everything we are doing with the dynamic 
     // parameters so a good-old-fashioned if.. then.. else... will suffice. 
     if (MySwitch) 
     { 
      // Now we are here at the precipice of this DynamicParameter cmdlet. 
      // Here is one way to get the value desired from the dynamic parameter. 

      // Simply access it like a dictionary... 
      var bar = DynamicParameters["Bar"].Value as string; 

      // The reason we can do it this way is because we assigned our 
      // beloved value to the local variable "DynmaicParameters" 
      // in the GetDynamicParameters() method. We could care less about 
      // the return value, because if the 
      // switch is flipped, "DynamicParameters" will be our new best friend, and 
      // it will have everything we need. 

      WriteWarning("Your " + bar + " has been forwarded to an automatic voice messaging system ..."); 
     } 


     WriteObject("Cheers was filmed before a live studio audience..."); 
     WriteObject(MyInvocation.BoundParameters); 
    } 
}