[英]Create PowerShell Cmdlets in C# - Pipeline chaining
I have some classes in C# which I would like to use them in pipelines, I've seen articles about it but I haven't been able to do it yet.我在 C# 中有一些类,我想在管道中使用它们,我已经看过有关它的文章,但我还没有做到。
Here's how I am using it right now:这是我现在使用它的方式:
$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')
And I want to be able to use it like this with pipelines:我希望能够像这样将它与管道一起使用:
$suite = [MyProject.SuiteBuilder]::CreateSuite('my house')
$suite | AddSet('doors', 'These represents doors') `
| AddOption('blue', 'kitchen') `
| AddOption('black', 'bedreoom') `
| AddOption('white', 'toilet')
Here are my C# classes:这是我的 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;
}
}
And I am struggling to make these function available to call in the pipeline form.我正在努力使这些 function 可以以管道形式调用。
I also added a comment like call this method in pipeline
before each comment that I need to call.我还在需要调用的每个注释之前添加了一条注释,例如call this method in pipeline
。
In short, you need to:简而言之,您需要:
[Parameter(ValueFromPipeline =true)]
使用[Parameter(ValueFromPipeline =true)]
接受来自管道的参数WriteObject
method in process method通过在 process 方法中调用WriteObject
方法将 output 提供给管道In this post I'll refactor your code a bit and will show you how you can create Powershell Cmdlet in C# and how to define parameters , accept parameter from pipeline and provide output to pipeline .在这篇文章中,我将对您的代码进行一些重构,并将向您展示如何在 C# 中创建Powershell Cmdlet以及如何定义参数、接受来自管道的参数并将Z78E6221F6393D1356681DB.D 管道提供给管道。 Then you can easily write something like:然后你可以很容易地写出类似的东西:
$suite = [MyCmdLets.Suite]::New("suite1")
$suite | Add-Set "type1" "desc1"`
| Add-Option "color1" "place1"`
| Add-Option "color2" "place2" | Out-Null
To do so, follow these steps:为此,请按照下列步骤操作:
MyCmdlets
)创建一个 C# class 库项目(例如将其命名为MyCmdlets
)Microsoft.PowerShell.5.ReferenceAssemblies
安装 Package Microsoft.PowerShell.5.ReferenceAssemblies
Create the cmdlets considering the following notes: (See the code at the bottom of post)考虑以下注意事项创建 cmdlet:(请参阅帖子底部的代码)
Cmdlet
class从Cmdlet
class 派生CmdletAttribute
attribute specifying the verb and the name after verb, for example if you want to have Add-Set
, use [Cmdlet(VerbsCommon.Add, "Set")]
.使用CmdletAttribute
属性来装饰 class,指定动词和动词后的名称,例如,如果您想要Add-Set
,请使用[Cmdlet(VerbsCommon.Add, "Set")]
。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))]
. 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))]
.Parameter
attribute.通过Parameter
属性装饰每个参数属性。ParameterAttribute
attribute, set ValueFromPipeline
to true, fro example [Parameter(ValueFromPipeline =true)
如果你想接受来自管道的参数,当使用ParameterAttribute
属性进行装饰时,将ValueFromPipeline
设置为 true,例如[Parameter(ValueFromPipeline =true)
ProcessRecord
and using WriteObject
write the to output.要将 output 提供给管道,请覆盖ProcessRecord
等管道处理方法并使用WriteObject
将其写入 output。Build the project.构建项目。
Open PowerShell ISE and run the following code:打开 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
It will create a structure like this:它将创建一个这样的结构:
Name Sets ---- ---- suite1 {MyCmdlets.Set} Type Description Options ---- ----------- ------- type1 desc1 {MyCmdlets.Option, MyCmdlets.Option} Color Place ----- ----- color1 place1 color2 place2
Model Classes Model 类
As mentioned above, design your model classes independent from PowerShell like this:如上所述,设计独立于 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 Classes CmdLet 类
Also design the cmdlet classes based on notes which I describe above:还要根据我上面描述的注释设计 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);
}
}
}
You can use ValueFromPipeline = $true.您可以使用 ValueFromPipeline = $true。 However, you will have to reference the type variable, and return the item if you want to continue the pipeline.但是,如果要继续流水线,则必须引用类型变量并返回项目。 I don't know of a way to work around this.我不知道解决这个问题的方法。 Since it will return, you would have to add an Out-Null
at the end to prevent it from hitting console.由于它会返回,因此您必须在末尾添加一个Out-Null
以防止它击中控制台。
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_ref?view=powershell-6 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.