jeudi 26 mai 2016

Design Patterns for PowerShell Cmdlets (in C#)

Working on a PowerShell Module in C# and something occurred to that seems logical but I can't find any other info to confirm or correct my assumptions.

Say I have one Cmdlet looks something like this

[Cmdlet(VerbsCommon.Get, CmdletHelpers.Noun, SupportsShouldProcess = true)]
[CmdletBinding]
public class GetSomething : PSCmdlet
{
    protected override void ProcessRecord() 
    { 
        var SomeCustomObject = new SomeCustomClass()
        WriteObject(SomeCustomObject); 
    }
}

Then say I have another Cmdlet which accepts a SomeCustomObject as a Parameter.

[Cmdlet(VerbsData.Import, CmdletHelpers.Noun)]
[CmdletBinding]
public class ImportSomething : PSCmdlet
{

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

    protected override void ProcessRecord()
    {
        // Do Something with SomeCustomObject
        // Return modified SomeCustomObject
        WriteObject(SomeCustomObject);
    }
}

So I would assume that a PowerShell Cmdlet that takes in a particular parameter should usually not modify the parameter and instead create a copy if changes need to be made to that parameter. However I can't find any definitive opinions on this.

In other words if I change my ProcessRecord above to

protected override void ProcessRecord()
{
    SomeCustomObject.ChangeSomething();
    WriteObject(SomeCustomObject);
}

If I have some PowerShell calls:

$SCO = Get-Something
$NewSCO = $SCO | Import-Something

$NewSCO AND $SCO BOTH would have been modified to the same state which seems bad, i.e. we'd always want the items upstream in the pipeline to retain their state so to speak so if later on we want to go back it always retains its original values when it was previously down stream of the Cmdlet that created it.

So instead (Assuming SomeCustomClass has a Copy Constructor) this should be the better design pattern.

protected override void ProcessRecord()
{
    var NewSomeCustomObject = new SomeCustomClass(SomeCustomObject);
    NewSomeCustomObject.ChangeSomething();
    WriteObject(NewSomeCustomObject);
} 

Am I completely off here?

Would there ever be a GOOD reason ESPECIALLY in the pipeline to modify a parameter object upstream of the current Cmdlet?

Aucun commentaire:

Enregistrer un commentaire