Delphi的属性语言特性可以用来注释哪些语言元素?

32

Delphi 2010引入了自定义属性,可以添加到类型声明和方法中。哪些语言元素可以使用自定义属性?

迄今为止我找到的示例包括类声明、字段和方法。(据我所知,泛型类不支持自定义属性)。

这篇文章中展示了一些示例。看起来变量(不属于任何类声明的外部变量)也可以有属性。

根据这篇文章,属性可用于:

  • 类和记录字段和方法
  • 方法参数
  • 属性
  • 非局部枚举声明
  • 非局部变量声明

还有其他语言元素可以放置属性吗?


更新:本文表明可以在属性之前放置自定义属性:http://francois-piette.blogspot.de/2013/01/using-custom-attribute-for-data.html

其中包含以下代码示例:

type
  TConfig = class(TComponent)
  public
    [PersistAs('Config', 'Version', '1.0')]
    Version : String;
    [PersistAs('Config', 'Description', 'No description')]
    Description : String;
    FTest : Integer;
    // No attribute => not persistent
    Count : Integer;
    [PersistAs('Config', 'Test', '0')]
    property Test : Integer read FTest write FTest;
  end;

我猜也许有一种方法可以读取方法参数上的属性,比如:

procedure Request([FormParam] AUsername: string; [FormParam] APassword: string);

2
有趣的问题。文档说明属性用于“注释类型和类型成员”-我怀疑这意味着type子句中的任何内容,以及记录或类内声明的任何内容(成员变量、属性、函数、过程、内部类等)。 - David
那个有关属性的链接对我来说无法使用。如果你记得它说了什么,是否介意编辑下面的答案以演示如何在属性上使用属性?(我找不到该链接的其他来源,因为引文中没有包括任何关于作者、主题、论坛甚至日期的内容。) - Rob Kennedy
@RobKennedy 谢谢您的注意!我找不到原始来源,但找到了另一篇文章并更新了问题。 - mjn
1个回答

29
有趣的问题!您可以在几乎任何东西上声明属性,问题是如何使用RTTI检索它们。这里是一个快速的控制台演示,用于声明以下自定义属性:
  • 枚举
  • 函数类型
  • 过程类型
  • 方法类型(of object
  • 别名类型
  • 记录类型
  • 类类型
  • 类内部的记录类型
  • 记录字段
  • 记录方法
  • 类实例字段
  • class字段(class var
  • 类方法
  • 全局变量
  • 全局函数
  • 局部变量

没有找到一种方法来为类的property声明自定义属性。但是,可以将自定义属性附加到getter或setter方法。

代码,在代码之后故事继续:

program Project25;

{$APPTYPE CONSOLE}

uses
  Rtti;

type
  TestAttribute = class(TCustomAttribute);

  [TestAttribute] TEnum = (first, second, third);
  [TestAttribute] TFunc = function: Integer;
  [TestAttribute] TEvent = procedure of object;
  [TestAttribute] AliasInteger = Integer;

  [TestAttribute] ARecord = record
    x:Integer;
    [TestAttribute] RecordField: Integer;
    [TestAttribute] procedure DummyProc;
  end;

  [TestAttribute] AClass = class
  strict private
    type [TestAttribute] InnerType = record y:Integer; end;
  private
    [TestAttribute]
    function GetTest: Integer;
  public
    [TestAttribute] x: Integer;
    [TestAttribute] class var z: Integer;
    // Can't find a way to declare attribute for property!
    property Test:Integer read GetTest;
    [TestAttribute] class function ClassFuncTest:Integer;
  end;

var [TestAttribute] GlobalVar: Integer;

[TestAttribute]
procedure GlobalFunction;
var [TestAttribute] LocalVar: Integer;
begin
end;

{ ARecord }

procedure ARecord.DummyProc;
begin
end;

{ AClass }

class function AClass.ClassFuncTest: Integer;
begin
end;

function AClass.GetTest: Integer;
begin
end;

begin
end.

麻烦的是检索那些自定义属性。查看 rtti.pas 单元,可以检索以下类型的自定义属性:
- 记录类型(TRttiRecordType) - 实例类型(TRttiInstanceType) - 方法类型(TRttiMethodType) - 指针类型(TRttiPointerType)- 用于什么? - 过程类型(TRttiProcedureType)
无法检索“单元”级别或局部变量和过程的任何类型的 RTTI,因此无法检索有关属性的信息。

2
不支持属性的属性很奇怪(也很遗憾 - 属性是 Delphi 类中令人惊叹的事物之一)。顺便说一句,对于出色的答案点赞。 - David
3
@David M:看我的更新,似乎属性在属性上的运作良好。 - mjn
过程和函数参数呢?它们可以有属性吗? - mjn

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