簡體   English   中英

在 C# 中創建 PowerShell Cmdlet - 管道鏈接

[英]Create PowerShell Cmdlets in C# - Pipeline chaining

我在 C# 中有一些類,我想在管道中使用它們,我已經看過有關它的文章,但我還沒有做到。

這是我現在使用它的方式:

$suite = [MyProject.SuiteBuilder]::CreateSuite('my house')

$houseSet = $suite.AddSet('doors', 'These represents doors')
$houseSet.AddOption('blue', 'kitchen')
$houseSet.AddOption('black', 'bedreoom')
$houseSet.AddOption('white', 'toilet')

我希望能夠像這樣將它與管道一起使用:

$suite = [MyProject.SuiteBuilder]::CreateSuite('my house')

$suite | AddSet('doors', 'These represents doors') `
       | AddOption('blue', 'kitchen') `
       | AddOption('black', 'bedreoom') `
       | AddOption('white', 'toilet')

這是我的 C# 類:

//SuiteBuilder.cs
public static class SuiteBuilder
{
    public static Suite CreateTestSuite(string name)
    {
        return new Suite(name);
    }
}

//Suite.cs
public class Suite : PSCmdlet
{
    public string Name { get; set; }
    public IEnumerable<Set> Sets { get; set; }

    public Suite(string name)
    {
        Name = name;
        Sets = new List<Set>();
    }

    // call this method in pipeline
    public Set AddSet(string type, string description)
    {
        Sets.Add(new Set(type, description));
        return Sets.Last();
    }
}


//Set.cs
public class Set : PSCmdlet
{
    public string Type { get; set; }
    public string Description { get; set; }
    public IEnumerable<Option> Options { get; set; }

    public Set(string type, string description)
    {
        Type = type;
        Description = description;
        Options = new List<Option>();
    }

    // call this method from pipeline
    public Set AddOption(string color, string place)
    {
        Options.Add(new Option(color, place));
        return this;
    }
}


//option.cs
public class Option : PSCmdlet
{
    public string Color { get; set; }
    public string Place { get; set; }

    public Option(string color, string place)
    {
        Color = color;
        Place = place;
    }
}

我正在努力使這些 function 可以以管道形式調用。

我還在需要調用的每個注釋之前添加了一條注釋,例如call this method in pipeline

簡而言之,您需要:

  • 使用[Parameter(ValueFromPipeline =true)]接受來自管道的參數
  • 通過在 process 方法中調用WriteObject方法將 output 提供給管道

詳細的一步一步的答案

在這篇文章中,我將對您的代碼進行一些重構,並將向您展示如何在 C# 中創建Powershell Cmdlet以及如何定義參數接受來自管道的參數並將Z78E6221F6393D1356681DB.D 管道提供給管道 然后你可以很容易地寫出類似的東西:

$suite = [MyCmdLets.Suite]::New("suite1")
$suite | Add-Set "type1" "desc1"`
       | Add-Option "color1" "place1"`
       | Add-Option "color2" "place2" | Out-Null

為此,請按照下列步驟操作:

  1. 創建一個 C# class 庫項目(例如將其命名為MyCmdlets
  2. 安裝 Package Microsoft.PowerShell.5.ReferenceAssemblies
  3. 創建您的 model 類,獨立於 PowerShell。 (見帖子底部的代碼)
  4. 考慮以下注意事項創建 cmdlet:(請參閱帖子底部的代碼)

    • 對於每個 cmdlet,創建一個 C# class
    • Cmdlet class 派生
    • 使用CmdletAttribute屬性來裝飾 class,指定動詞和動詞后的名稱,例如,如果您想要Add-Set ,請使用[Cmdlet(VerbsCommon.Add, "Set")]
    • If you want to have an output for pipeline, decorate the class with OutputTypeAttribute attribute specifying the type of output, for example if you want to have an output of type Set for the pipeline, use [OutputType(typeof(Set))] .
    • 根據 cmdlet 的每個輸入參數,定義一個 C# 屬性。
    • 通過Parameter屬性裝飾每個參數屬性。
    • 如果你想接受來自管道的參數,當使用ParameterAttribute屬性進行裝飾時,將ValueFromPipeline設置為 true,例如[Parameter(ValueFromPipeline =true)
    • 要將 output 提供給管道,請覆蓋ProcessRecord等管道處理方法並使用WriteObject將其寫入 output。
  5. 構建項目。

  6. 打開 PowerShell ISE 並運行以下代碼:

     Import-Module "PATH TO YOUR BIN DEBUG FOLDER\MyCmdlets.dll" $suite = [MyCmdLets.Suite]::New("suite1") $suite | Add-Set "type1" "desc1"` | Add-Option "color1" "place1"` | Add-Option "color2" "place2" | Out-Null

    它將創建一個這樣的結構:

     Name Sets ---- ---- suite1 {MyCmdlets.Set} Type Description Options ---- ----------- ------- type1 desc1 {MyCmdlets.Option, MyCmdlets.Option} Color Place ----- ----- color1 place1 color2 place2

示例代碼

Model 類

如上所述,設計獨立於 PowerShell 的 model 類,如下所示:

using System.Collections.Generic;
namespace MyCmdlets
{
    public class Suite
    {
        public string Name { get; set; }
        public List<Set> Sets { get; } = new List<Set>();
        public Suite(string name) {
            Name = name;
        }
    }
    public class Set
    {
        public string Type { get; set; }
        public string Description { get; set; }
        public List<Option> Options { get; } = new List<Option>();
        public Set(string type, string description) {
            Type = type;
            Description = description;
        }
    }
    public class Option 
    {
        public string Color { get; set; }
        public string Place { get; set; }
        public Option(string color, string place) {
            Color = color;
            Place = place;
        }
    }
}

CmdLet 類

還要根據我上面描述的注釋設計 cmdlet 類:

using System.Management.Automation;
namespace MyCmdlets
{
    [Cmdlet(VerbsCommon.Add, "Set"), OutputType(typeof(Set))]
    public class AddSetCmdlet : Cmdlet
    {
        [Parameter(ValueFromPipeline = true, Mandatory = true)]
        public Suite Suite { get; set; }
        [Parameter(Position = 0, Mandatory = true)]
        public string Type { get; set; }
        [Parameter(Position = 1, Mandatory = true)]
        public string Description { get; set; }
        protected override void ProcessRecord() {
            var set = new Set(Type, Description);
            Suite.Sets.Add(set);
            WriteObject(set);
        }
    }

    [Cmdlet(VerbsCommon.Add, "Option"), OutputType(typeof(Option))]
    public class AddOptionCmdlet : Cmdlet
    {
        [Parameter(ValueFromPipeline = true, Mandatory = true)]
        public Set Set { get; set; }
        [Parameter(Position = 0, Mandatory = true)]
        public string Color { get; set; }
        [Parameter(Position = 1, Mandatory = true)]
        public string Place { get; set; }
        protected override void ProcessRecord() {
            var option = new Option(Color, Place);
            Set.Options.Add(option);
            WriteObject(Set);
        }
    }
}

您可以使用 ValueFromPipeline = $true。 但是,如果要繼續流水線,則必須引用類型變量並返回項目。 我不知道解決這個問題的方法。 由於它會返回,因此您必須在末尾添加一個Out-Null以防止它擊中控制台。

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_ref?view=powershell-6

function Add-Option {
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [ref]$Item,
        [Parameter(Mandatory = $true, Position = 0)]
        [String]$Color
        [Parameter(Mandatory = $true, Position = 1)]
        [String]$Room
    )
    $Item.Value.AddOption($Color,$Room)
    return $Item
}

$suite = [MyProject.SuiteBuilder]::CreateSuite('my house')

[ref]$suite | Add-Option 'blue' 'kitchen' `
            | Add-Option 'black' 'bedroom' `
            | Out-Null

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM