在C#管道链接中创建PowerShell cmdlet

在C#管道链接中创建PowerShell cmdlet,c#,powershell,cmdlet,C#,Powershell,Cmdlet,我有一些C#中的类,我想在管道中使用它们,我看过关于它的文章,但我还没有能够做到这一点 下面是我现在使用它的方式: $suite = [MyProject.SuiteBuilder]::CreateSuite('my house') $houseSet = $suite.AddSet('doors', 'These represents doors') $houseSet.AddOption('blue', 'kitchen') $houseSet.AddOption('black', 'be

我有一些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
公共静态类SuiteBuilder
{
公共静态套件CreateTestSuite(字符串名称)
{
返回新套房(姓名);
}
}
//Suite.cs
公共类套件:PSCmdlet
{
公共字符串名称{get;set;}
公共IEnumerable集合{get;set;}
公共套件(字符串名称)
{
名称=名称;
集合=新列表();
}
//在管道中调用此方法
公共集AddSet(字符串类型、字符串描述)
{
添加(新集合(类型、说明));
返回集合.Last();
}
}
//Set.cs
公共类集:PSCmdlet
{
公共字符串类型{get;set;}
公共字符串说明{get;set;}
公共IEnumerable选项{get;set;}
公共集(字符串类型、字符串描述)
{
类型=类型;
描述=描述;
选项=新列表();
}
//从管道调用此方法
公共设置添加选项(字符串颜色、字符串位置)
{
选项。添加(新选项(颜色、位置));
归还这个;
}
}
//option.cs
公共类选项:PSCmdlet
{
公共字符串颜色{get;set;}
公共字符串Place{get;set;}
公共选项(字符串颜色、字符串位置)
{
颜色=颜色;
地点=地点;
}
}
我正在努力使这些函数能够以管道形式调用


在我需要调用的每个注释之前,我还添加了一条注释,如
在管道中调用此方法。

您可以使用valuefrompipline=$true。但是,如果要继续管道,则必须引用类型变量并返回项。我不知道如何解决这个问题。由于它将返回,您必须在末尾添加一个
Out Null
,以防止它击中控制台

简而言之,您需要:

  • 使用
    [参数(ValueFromPipeline=true)]从管道接受参数
  • 通过调用process方法中的
    WriteObject
    方法向管道提供输出
详细的逐步回答 在这篇文章中,我将对您的代码进行一点重构,并向您展示如何在C#中创建,以及如何定义参数从管道中接受参数,以及向管道提供输出。然后你可以很容易地写下如下内容:

$suite=[mycmdlet.suite]::新建(“suite1”)
$suite |添加设置“类型1”“说明1”`
|添加选项“color1”“place1”`
|添加选项“color2”“place2”| Out Null
为此,请执行以下步骤:

  • 创建一个C#类库项目(例如,命名它
    mycmdlet
  • 安装软件包
  • 创建独立于PowerShell的模型类。(见帖子底部的代码)
  • 创建cmdlet时请考虑以下注意事项:(请参阅文章底部的代码)

    • 根据每个cmdlet,创建一个C#类
    • 源于类
    • 使用指定动词和动词后的名称的属性来修饰类,例如,如果您希望使用
      添加集
      ,请使用
      [Cmdlet(VerbsCommon.Add,“Set”)]
    • 如果希望管道具有输出,请使用指定输出类型的属性装饰该类,例如,如果希望管道具有
      Set
      类型的输出,请使用
      [OutputType(typeof(Set))]
    • 根据cmdlet的每个输入参数,定义一个C#属性
    • 通过
      参数
      属性装饰每个参数属性
    • 如果要接受管道中的参数,在使用属性装饰时,请从示例
      [参数(ValueFromPipeline=true)
    • 要向管道提供输出,请重写管道处理方法,如和,并使用写入输出
  • 构建项目

  • 打开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
    
    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;
            }
        }
    }
    
  • 示例代码 模型类

    如上所述,独立于PowerShell设计模型类,如下所示:

    Name   Sets           
    ----   ----           
    suite1 {MyCmdlets.Set}
    
    
    Type  Description Options                             
    ----  ----------- -------                             
    type1 desc1       {MyCmdlets.Option, MyCmdlets.Option}
    
    
    Color  Place 
    -----  ----- 
    color1 place1
    color2 place2
    
    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;
            }
        }
    }
    

    为什么使用管道?不会(对不起,我不能在注释中添加换行符,请继续想象它们)
    $houseSet=$suite.AddSet('doors','this represents doors')。AddOption('blue','kitchen')。AddOption('black','bedroom')。AddOption('white','doctor'))
    够了吗?这是一个非复杂的折衷方案,可以在代码上工作,甚至不需要对代码进行任何更改。@ensinoctis是的,但只是管道看起来非常清晰。它说您需要用System.Management.Automation.ParameterAttribute来修饰参数,如
    [参数(ValueFromPipeline=true)]
    注意:我将AddOption改为为为正确的模式添加选项,但如果需要,可以使用AddOption。
    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);
            }
        }
    }