繁体   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