F# 创建自定义属性以表达式

12

在 F# 中,我如何创建一个 自定义属性 并将其应用于表达式?我已经到处寻找资源,但没有找到任何东西。

例如,属性[<Entrypoint>] 可以应用于某些表达式,从而使编译器可以推断该表达式应该是类型array string -> int

我如何创建一个类似的自定义属性?

1个回答

19

要创建自定义属性,只需声明一个继承自 System.Attribute 的类:

type MyAttribute() = inherit System.Attribute()

[<My>]
let f x = x+1

你可以看到,在将属性应用于代码单元时,后缀"Attribute"可以省略。可选地,你可以为属性指定参数或属性:

type MyAttribute( x: string ) =
    inherit System.Attribute()
    member val Y: int = 0 with get, set

[<My("abc", Y=42)>]
let f x = x+1

在运行时,您可以检查类型、方法和其他代码单元,以查看应用于它们的属性,并检索其数据:

[<My("abc", Y=42)>]
type SomeType = A of string

for a in typeof<SomeType>.GetCustomAttributes( typeof<MyAttribute>, true ) do 
    let my = a :?> MyAttribute
    printfn "My.Y=%d" my.Y

// Output:
> My.Y=42

这里有一个教程,更详细地解释了自定义属性。

然而,你不能使用自定义属性来强制编译时行为。 EntryPointAttribute特殊的 - 也就是说,F#编译器知道它的存在并给予特殊处理。 F#中有一些其他特殊的属性 - 例如,NoComparisonAttributeCompilationRepresentationAttribute等,-但您无法告诉编译器给予您自己创建的属性特殊处理。

如果您描述您的更大目标(即您要实现的目标),我确信我们将能够找到更好的解决方案。


1
我在想编译器是否能够从属性中推断出,但并没有更大的目标。但我不知道有任何特殊的属性,谢谢! - Francisco Berrocal
在 F# 中是否有一种方法可以代替 typeof<SomeType>,以便对模块中的所有类型执行操作?我想捕获所有顶层 let,这些 let 带有某些属性的注释,如果我错过了其中一个,就会测试失败。 - John Zabroski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接