扫描给定自定义属性的所有类

Mar*_*ius 3 delphi attributes class delphi-xe

我正在寻找一种扫描所有加载类的方法,如果可能的话,包含自定义属性的类,而不使用RegisterClass().

ter*_*ran 7

首先你必须创建TRttiContext,然后使用所有加载的类getTypes.之后你可以过滤类型TypeKind = tkClass; 下一步是枚举属性并检查它是否具有您的属性;

属性和测试类级别:

unit Unit3;

interface
type
    TMyAttribute = class(TCustomAttribute)
    end;

    [TMyAttribute]
    TTest = class(TObject)

    end;

implementation

initialization
    TTest.Create().Free();  //if class is not actually used it will not be compiled

end.
Run Code Online (Sandbox Code Playgroud)

然后找到它:

program Project3;
{$APPTYPE CONSOLE}

uses
  SysUtils, rtti, typinfo, unit3;

type TMyAttribute = class(TCustomAttribute)

     end;

var ctx : TRttiContext;
    t : TRttiType;
    attr : TCustomAttribute;
begin
    ctx := TRttiContext.Create();

    try
        for t  in ctx.GetTypes() do begin
            if t.TypeKind <> tkClass then continue;

            for attr in t.GetAttributes() do begin
                if attr is TMyAttribute then begin
                    writeln(t.QualifiedName);
                    break;
                end;
            end;
        end;
    finally
        ctx.Free();
        readln;
    end;
end.
Run Code Online (Sandbox Code Playgroud)

输出是 Unit3.TTest

调用RegisterClass在流系统中注册一个类....一旦注册了类,它们就可以被组件流系统加载或保存.

因此,如果您不需要组件流(只需查找具有某些属性的类),则无需执行此操作RegisterClass

  • @teran它是按需创建的,无论如何,所以如果你想要清除旧的,那么当你完成时调用`Free`.我个人觉得这种风格(如Embarcadero所示)使记录看起来像是一种相当误导的类.我宁愿他们没有在记录中使用`Create`和`Free`,因为它让代码的读者知道`ctx`是堆分配的引用类型.它不过是. (4认同)

Dav*_*nan 5

您可以使用 Rtti 单元公开的新 RTTI 功能。

var
  context: TRttiContext;
  typ: TRttiType;
  attr: TCustomAttribute;
  method: TRttiMethod;
  prop: TRttiProperty;
  field: TRttiField;
begin
  for typ in context.GetTypes do begin
    for attr in typ.GetAttributes do begin
      Writeln(attr.ToString);
    end;

    for method in typ.GetMethods do begin
      for attr in method.GetAttributes do begin
        Writeln(attr.ToString);
      end;
    end;

    for prop in typ.GetProperties do begin
      for attr in prop.GetAttributes do begin
        Writeln(attr.ToString);
      end;
    end;

    for field in typ.GetFields do begin
      for attr in field.GetAttributes do begin
        Writeln(attr.ToString);
      end;
    end;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

此代码枚举与方法、属性和字段以及类型关联的属性。当然,您想要做的不仅仅是Writeln(attr.ToString),但这应该让您知道如何继续。您可以以正常方式测试您的特定属性

if attr is TMyAttribute then
  ....
Run Code Online (Sandbox Code Playgroud)