每一次和一段时间我偶尔冒着能力的东西,我发现有趣,我无法帮助潜入它。我看到了一条推文 布兰登奥林 最近显示您可以在PowerShell中创建自己的自定义og体育。

我们可以享受很多乐趣。

这是原始的一个帖子,但由于长度,我将其崩溃成两个部分。

在开始之前,明白这是一个非常先进的技术,我们即将深入潜入它。

指数

什么是og体育?

它们允许您将其他信息附加到类,函数和og体育。它是您的代码的元数据。让我告诉你一些例子。

高级功能中的示例

Powershell already makes use of them in advanced functions. You can specify the [Property(Mandatory=$true)] attribute for a property to make it required. You can add the [ValidateNotNullOrEmpty] attribute to make sure it has a value.

function Do-Something 
{
    [cmdletbinding()]
    param(
        [Property(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        $Path
    )
    ...
}

psscriptanalyzer提示

psscriptanalyzer. has a lot of good best practices that it will check. Sometimes you need to do something a little different and you don’t want PSScriptAnalyzer complaining. You could exclude that one rule for everything or use an attribute like [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingInvokeExpression","")] to 压制 脚本中的一个发生。

创建自己的og体育

您也可以通过继承来创建自己的 og体育 .

 Class MyCommand : Attribute {}

如果我们创建默认构造函数,我们可以将值传递到我们的og体育中并稍后访问它们。

Class MyCommand : Attribute {
    [string]$Name

    MyCommand([string]$Name)
    {
        $this.Name = $Name
    }
}

附加我们的自定义og体育

然后我们可以将它附加到我们的类,og体育和函数中。

[MyCommand('MyClass')]
class Test {

    [MyCommand('MyClassProperty')]
    $Name = 'TestName'

    [MyCommand('myFunction')]
    [string] SayHello(
        [string]
        $Name = "Kevin"
    )
    {
        return "Hello $name"
    }
}

我在三个位置附加了我们的og体育,并给出了我们可以通过反射发现的自定义价值。以下是高级功能的示例。

function Do-Something
{
    [MyCommand('MyAdvancedFunction')]
    [cmdletbinding()]
    param()
    return $true
}

访问我们的og体育

Now that we have an attribute and attached it to something, we can use GetCustomAttributes('MyCommand') to read our values.

# on our class
[Test].GetCustomAttributes('MyCommand')

# on our class property named Name
[Test].GetMember('Name').GetCustomAttributes('MyCommand')
[Test].GetProperty('Name').GetCustomAttributes('MyCommand')

# on our method named SayHello
[Test].GetMember('SayHello').GetCustomAttributes('MyCommand')
[Test].GetMethod('SayHello').GetCustomAttributes('MyCommand')

高级功能有点不同,但信息仍然存在。

$command = Get-Command Do-Something
$command.ScriptBlock.Attributes | Where-object {$_.TypeID.Name -eq 'MyCommand'}

I had to filter on the TypeID.Name because we will also get the [CmdLetBinding()] attribute too if we don’t use a filter.

它在课堂上而不是对象

请记住,og体育是我们代码的元数据。所以它是具有附加og体育的类。该类的每个对象都具有与相同值相同的og体育。

$object = [Test]::new()
$object.GetType().GetCustomAttributes('MyCommand')

从对象获取我们的og体育的唯一方法是将其从对象类型拉出。如果您发现这是您的问题,请重新考虑使用og体育。对于您正在尝试的任何内容,类og体育或函数参数可能是更好的选择。

我们能用这怎么办?

这 most obvious use to me is giving hints to our testing framework like in my psscriptanalyzer. example above. A lot of tests we make in Pester are specific to the functions we are testing, but I often have tests that walk everything.

以下是所有作品的快速示例。

Skiptestog体育

以下是此示例的新og体育。

Class SkipTest : Attribute {
    [string]$TestName

    MyCommand([string]$Name)
    {
        $this.TestName = $Name
    }
}

样本功能

我们将它附加到高级功能。

function Do-Something
{
    [SkipTest('HelpDescription')]
    [cmdletbinding()]
    param()
    return $true
}

助手功能

我决定创建一个辅助功能,使得更容易使用。

function ShouldRunTest
{
    [cmdletbinding()]
    param(
        [System.Management.Automation.CommandInfo]
        $Command,

        [string]
        $TestName
    )
    $SkipTest = $Command.ScriptBlock.Attributes | Where-object { $_.TypeID.Name -eq 'SkipTest' }
    
    if( ( $SkipTest -ne $null ) -and ( $SkipTest.TestName -eq $TestName ) )
    {
        return $false
    }

    return $true
}

这将使我们的测试看起来很清洁

纠演试验

然后我们更新我们的测试以检查og体育。假设这是一个完整的模块,我们有很多我们正在测试的功能,但想要排除上面的功能。

Describe "Help tests for $moduleName" -Tags Build {

    $functionList = Get-Command -Module $moduleName
    
    foreach($function in $functionList)
    {         
        if(ShouldRunTest $function -TestName 'HelpDescription')
        {
            It "has a help description" {
                $help = $function | %{Get-Help $_.name}
                $help.description | Should Not BeNullOrEmpty
            }
        }
    }
}

有限的应用

我肯定是用有限的应用程序作为一个高级功能。我相信你可以用这个功能非常有创意。我可以在这里停下来,但我想看到我们能够推动这一点。

如果我们找到了创建PowerShell已经了解如何使用的新og体育的方法怎么样?

让我知道

如果您找到将此信息放入使用的好方法,请告诉我。我很乐意看到一些实际实现。