C# 具有多个自定义属性的PowerShell方法

C# 具有多个自定义属性的PowerShell方法,c#,powershell,powershell-5.0,C#,Powershell,Powershell 5.0,我无法在PowerShell 5.0类方法上使用多个自定义属性(decorator)。在C#中,我能够做到以下几点: public class SomeAttribute : Attribute { public string Text { get; set; } } public class OtherAttribute : Attribute { public string Text { get; set; } } public class MyClass { [

我无法在PowerShell 5.0类方法上使用多个自定义属性(decorator)。在C#中,我能够做到以下几点:

public class SomeAttribute : Attribute {
    public string Text { get; set; }
}

public class OtherAttribute : Attribute {
    public string Text { get; set; }
}

public class MyClass {
    [SomeAttribute(Text = "sometext")]
    [OtherAttribute(Text = "othertext")]
    public void MyMethod() {
        // ...
    }
}
然后到别的地方打电话

object[] customAttributes = typeof(MyClass).GetMethod("MyMethod").GetCustomAttributes(false);
它为我提供了一个包含与该方法关联的所有自定义属性的数组,没有任何问题

在PowerShell 5.0中,我尝试以类似方式使用:

class SomeAttribute : Attribute {
    [string]$Text
}

class OtherAttribute : Attribute {
    [string]$Text
}

class MyClass {
    [SomeAttribute(Text="sometext")]
    [OtherAttribute(Text="othertext")]
    MyMethod() {
        # ...
    }
}
这似乎是正确的语法,PowerShell很乐意接受它。但是通过

[MyClass].GetMethod("MyMethod").GetCustomAttributes($false)
返回以下错误:

Exception calling "GetCustomAttributes" with "1" argument(s): "Could not load type 'OtherAttribute' from assembly '⧹powershell, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'."
At line:1 char:1
+ [MyClass].GetMethod("MyMethod").GetCustomAttributes($false)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : TypeLoadException

只需返回
$null

但是,当我只使用一个自定义属性时,一切都按预期工作,并且使用上面的代码段正确返回该属性。
如何为PowerShell 5.0类方法正确定义多个自定义属性

更新-仅使用一个自定义属性的行为示例 让我们仅假设原始问题中的第一个自定义属性

class SomeAttribute : Attribute {
    [string]$Text
}

class MyClass {
    [SomeAttribute(Text="sometext")]
    MyMethod() {
        # ...
    }
}
然后

给出以下输出

Text     TypeId
----     ------
sometext SomeAttribute
AttributeType Constructor  ConstructorArguments NamedArguments
------------- -----------  -------------------- --------------
SomeAttribute Void .ctor() {}                   {Text = "sometext"}

给出以下输出

Text     TypeId
----     ------
sometext SomeAttribute
AttributeType Constructor  ConstructorArguments NamedArguments
------------- -----------  -------------------- --------------
SomeAttribute Void .ctor() {}                   {Text = "sometext"}

这让我相信,一个属性确实可以像预期的那样工作。

即使只使用一个自定义属性,我也怀疑您是否真的得到了预期的结果。原因是方法不支持属性,至少我发现了这一点。一个方法支持一个可选的返回类型,在PowerShell中,该返回类型恰好看起来像一个属性。也就是说,您可以定义一个返回void的方法

MyMethod() {
    $foo = 5        
}
或者一个返回某些内容的方法(在本例中为int)

(不过,我希望有人能证明我错了,并证明PowerShell类确实支持属性!)

似乎PowerShell(.NET,IMHO)在引用具有相同全名的两个不同程序集时遇到问题(有人告诉我,在.NET中不可能)

PS>A类{}
PS>B类{}
PS>[A]。程序集-等式[B]。程序集
假的
PS>[A].Assembly.FullName-eq[B].Assembly.FullName
真的
PS>类CA{[A]$A};类CB{[B]$B}
PS>[CA]::新建().A#工作正常
PS>[CB]::new().B#错误
解决方案是在同一个命令中定义类
A
B
,这将把它们放在同一个生成的程序集中:

PS>A类{};B类{}
PS>[A]。程序集-等式[B]。程序集
真的
PS>类CA{[A]$A};类CB{[B]$B}
PS>[CA]::新建().A#工作正常
PS>[CB]::新建().B#工作正常
因此,这项工作对我来说很好:

PS>class-SomeAttribute:Attribute{
>>>[字符串]$Text
>>> }
>>>类OtherAttribute:属性{
>>>[字符串]$Text
>>> }
PS>类MyClass{
>>>[SomeAttribute(Text=“sometext”)]
>>>[OtherAttribute(Text=“othertext”)]
>>>MyMethod(){
>>>         # ...
>>>     }
>>> }
PS>[MyClass].GetMethod(“MyMethod”).GetCustomAttributes($false)
文本类型ID
----      ------
sometext SomeAttribute
其他文本其他属性

另一个解决方案是不在交互会话中定义类,而是在脚本文件中定义类。在这种情况下,模糊文件名将是生成的程序集名称的一部分,因此即使在不同的脚本文件中定义了属性,也不会有这种问题。

我更新了问题,以显示当我只使用一个属性时,我得到的是什么类型的输出(以及是什么让我相信它工作正常)。问题是我也找不到任何合适的文档,所以它可能只是巧合地与一个属性一起工作,或者我只是忽略了一些基本的东西。奇怪。。。当我试图只定义这两个类就执行您的代码时,我得到了不同的行为,特别是一个运行时异常,声明“创建管道时出错”。如果我删除第二个类上的属性,那么它将无错误地执行。您正在运行哪个特定的PS版本($host.version)?我的是5.0.10586.494。我的是5.1.14393.0(赢10分RS1)。是的,似乎是这样。在一次过中定义所有属性与在单独的脚本(包括脚本)中定义属性一样有效。但是,我不能使用交互式会话中的空行来保持可读性,我不能直接使用包含在脚本中的属性,因为我试图引用尚未完全定义的程序集。似乎PowerShell还没有准备好进行类似C的编程。遗憾的是,我不能使用交互式会话中的空行来维护可读性<代码>移位< /代码> +<代码>输入< /代码>工作。我无法直接在包含的脚本中使用属性。您可以将属性放在单独的
.psm1
文件中,并使用模块在脚本文件的开头添加
。\MyAttributes.psm1
。它看起来像一个bug,应该可以引用同一脚本文件中定义的属性。
MyMethod() {
    $foo = 5        
}
[int] MyMethod() {
    $foo = 5
    return $foo
}