1

I am working on preparing PowerShell cmdlet and have to set unique combinations for the inputs such that at a time only a given combination can be applied otherwise it should throw parameter set cannot be resolved using the specified named parameters.

public abstract class ServerCmdletBase
{
    public const string IdParameterSetName = "Id";
    public const string InputObjectParameterSetName = "InputObject";

    [Parameter(Mandatory = true, ParameterSetName = IdParameterSetName)]
    public int[] Id { get; set; }

    [Parameter(Mandatory = true, ParameterSetName = InputObjectParameterSetName)]
    public string[] InputObject { get; set; }

    ...
    ...
}
public class EditServerCmdlet : ServerCmdletBase
{
    public const string ConnectionStringParameterSetName = "ConnectionString";
    public const string PasswordParameterSetName = "Password";

    [Parameter(Mandatory = true, ParameterSetName = ConnectionStringParameterSetName)]
    [Parameter(ParameterSetName = IdParameterSetName )]
    [Parameter(ParameterSetName = InputObjectParameterSetName )]
    public string ConnectionString { get; set; }

    [Parameter(Mandatory = true, ParameterSetName = PasswordParameterSetName)]
    [Parameter(ParameterSetName = IdParameterSetName )]
    [Parameter(ParameterSetName = InputObjectParameterSetName )]
    public string Username { get; set; }

    [Parameter(Mandatory = true, ParameterSetName = PasswordParameterSetName)]
    [Parameter(ParameterSetName = IdParameterSetName )]
    [Parameter(ParameterSetName = InputObjectParameterSetName )]
    public string Password { get; set; }

    ...
    ...
}

The end goal is -Id and -InputObject should not be used at the same time. For the given input (Id or InputObject), -ConnectionString and -Username, -Password should not be used at the same time. Hence total 4 unique combinations.

I am using ParameterSetName here but can't get it to work. The above code only works for Id and InputObject, it can't handle ConnectionString/Username & Password. Please advise for the right approach. Thanks a lot!

1 Answer 1

2

Like you have identified 4 different combinations, you also need 4 different parameter sets. 1 combination corresponds to 1 set of parameters.

Since you're using a base class I don't think there's an easy way to reuse the code. So if the extending class needs to expand the number of possible sets and those sets need to include the parameters from the "base sets", you need to override the properties I believe.

Start by making them virtual:

public abstract class ServerCmdletBase
{
    public const string IdParameterSetName = "Id";
    public const string InputObjectParameterSetName = "InputObject";

    [Parameter(Mandatory = true, ParameterSetName = IdParameterSetName)]
    public virtual int[] Id { get; set; }

    [Parameter(Mandatory = true, ParameterSetName = InputObjectParameterSetName)]
    public virtual string[] InputObject { get; set; }

    ...
    ...
}

Now, create your 4 different set names and annotate the properties with those:

public class EditServerCmdlet : ServerCmdletBase
{
    public const string IdConnStrParameterSetName = IdParameterSetName + "ConnectionString";
    public const string InObjConnStrParameterSetName = InputObjectParameterSetName + "ConnectionString";
    public const string IdPwParameterSetName = IdParameterSetName + "Password";
    public const string InObjPwParameterSetName = InputObjectParameterSetName + "Password";

    [Parameter(Mandatory = true, ParameterSetName = IdConnStrParameterSetName)]
    [Parameter(Mandatory = true, ParameterSetName = IdPwParameterSetName)]
    public override int[] Id { get; set; }

    [Parameter(Mandatory = true, ParameterSetName = InObjConnStrParameterSetName)]
    [Parameter(Mandatory = true, ParameterSetName = InObjPwParameterSetName)]
    public override string[] InputObject { get; set; }

    [Parameter(Mandatory = true, ParameterSetName = IdConnStrParameterSetName)]
    [Parameter(Mandatory = true, ParameterSetName = InObjConnStrParameterSetName)]
    public string ConnectionString { get; set; }

    [Parameter(Mandatory = true, ParameterSetName = IdPwParameterSetName)]
    [Parameter(Mandatory = true, ParameterSetName = InObjPwParameterSetName)]
    public string Username { get; set; }

    [Parameter(Mandatory = true, ParameterSetName = IdPwParameterSetName)]
    [Parameter(Mandatory = true, ParameterSetName = InObjPwParameterSetName)]
    public string Password { get; set; }

    ...
    ...
}

Note: this means IdParameterSetName and InputObjectParameterSetName are essentially unused. So, unless you have other classes that derive from ServerCmdletBase that don't need to add other sets, you can probably remove those two "base sets".

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot, mate, it works. Just another minor question, if we have other optional parameters that we would like to provide with Id and InputObject but without ConnectionString/Username & Password this time. How can we support 2 more combinations along with those 4 from the earlier section?
@NiravJadeja Good to hear. In that case you'd just have to add two more parameter sets and specify that parameter as not mandatory. Think of parameter sets as C# method overloads - each overload directly corresponds to a unique parameter set.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.