首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在PowerShell 5中定义和使用自定义属性?

如何在PowerShell 5中定义和使用自定义属性?
EN

Stack Overflow用户
提问于 2020-12-24 20:41:37
回答 1查看 258关注 0票数 2

在Windows 10上使用PowerShell 5.1.14393.3866,我尝试在Powershell类属性上定义和使用自定义属性,如下所示:

代码语言:javascript
运行
复制
class MarkedAttribute : System.Attribute { }

class Person {
    [Marked()]
    [string]$Name
}

$p = [Person]::new()
$p.Name = "Hoho"

Write-Host $p.Name

当我运行前面的脚本时,我会得到以下错误:

代码语言:javascript
运行
复制
At C:\Users\xxxxxxxx\Desktop\FinishLine\issue.ps1:6 char:6
+     [Marked()]
+      ~~~~~~
Cannot find the type for custom attribute 'Marked'. Make sure that the assembly that contains this type is loaded.
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : CustomAttributeTypeNotFound

就好像从来没有定义过自定义属性一样。

我能够使用“标准”属性,比如在System.ComponentModel中定义的属性,但没有可能使用自定义属性。

我尝试了以下但没有成功:

  • 使用完整的属性名[MarkedAttribute()]
  • 在C#中定义属性并执行Add-Type -TypeDefinition $theCsCode

根据网上的一些帖子,应该可以使用来自PowerShell的自定义属性。

我遗漏了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-24 21:50:53

有两个问题(在PowerShell 7.1中编写):

  • 类定义在解析时被处理,此时任何引用类型都必须已经定义;也就是说,必须定义[MarkedAttribute]类型,然后才能使用对其的引用声明[Person]类型。
代码语言:javascript
运行
复制
- To work around that in a single script, you need [`Invoke-Expression`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/invoke-expression), though do note that [`Invoke-Expression` should generally be avoided](https://blogs.msdn.microsoft.com/powershell/2011/06/03/invoke-expression-considered-harmful/)
  • 一旦满足了这一要求,另外--出于我不知道的原因--需要显式的Attribute后缀来引用类型。
代码语言:javascript
运行
复制
- This unexpected additional requirement is discussed in [GitHub issue #14499](https://github.com/PowerShell/PowerShell/issues/14499).
代码语言:javascript
运行
复制
class MarkedAttribute : System.Attribute { }

# Use Invoke-Expression so you can refer to [MarkedAttribute] if defined
# in the same script, 
# and be sure to use the 'Attribute' suffix explicitly.
Invoke-Expression @'
  class Person {
    [MarkedAttribute()]
    [string]$Name
  }
'@

$p = [Person]::new()
$p.Name = "Hoho"

$p.Name # output

如果您想避免对Invoke-Expression的需求,请将[Person]类定义外包到一个单独的文件中,然后可以使用. ( 点源运算符 )加载到当前范围中。

首先,创建一个PersonClass.ps1文件,其中包含与将要使用它的脚本相同的目录中的Person类定义:

代码语言:javascript
运行
复制
@'
class Person {
  [MarkedAttribute()]
  [string]$Name
}
'@ > PersonClass.ps1

然后按照以下方式定义主脚本:

代码语言:javascript
运行
复制
class MarkedAttribute : System.Attribute { }

# Dot-source the script that defines the [Person] class, from the
# same dir. where this script resides:
. $PSScriptRoot/PersonClass.ps1

$p = [Person]::new()
$p.Name = "Hoho"

$p.Name # output

这种方法确保在解析[MarkedAttribute]时已经定义了类PersonClass.ps1,因此[Person]的定义成功了。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65443073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档