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

Class 为给定的自定义属性扫描所有类,class,delphi,attributes,delphi-xe,Class,Delphi,Attributes,Delphi Xe,我正在寻找一种方法,可以在不使用RegisterClass()的情况下扫描所有加载的类,查找包含自定义属性的类。首先,您必须创建TRttiContext,然后使用getTypes获取所有加载的类。之后,您可以通过TypeKind=tkClass过滤类型; 下一步是枚举属性并检查它是否具有您的属性 属性和测试类增量: unit Unit3; interface type TMyAttribute = class(TCustomAttribute) end; [TMyAt

我正在寻找一种方法,可以在不使用RegisterClass()的情况下扫描所有加载的类,查找包含自定义属性的类。

首先,您必须创建
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.
然后找到它:

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.
程序项目3;
{$APPTYPE控制台}
使用
SysUtils、rtti、typinfo、unit3;
类型TMyAttribute=class(TCustomAttribute)
结束;
var-ctx:TRttiContext;
t:trtti型;
属性:TCustomAttribute;
开始
ctx:=TRttiContext.Create();
尝试
对于ctx.GetTypes()中的t
如果是t.TypeKind tkClass,则继续;
对于t.GetAttributes()中的attr,请执行begin
如果attr是TMyAttribute,则开始
writeln(t.QualifiedName);
打破
结束;
结束;
结束;
最后
ctx.Free();
readln;
结束;
结束。
输出为单元3。t测试

调用RegisterClass向流媒体系统注册一个类。。。。注册类后,组件流系统即可加载或保存这些类


因此,如果您不需要组件流(只需查找具有某些属性的类),则无需注册类

,您可以使用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;
此代码枚举与方法、属性和字段以及类型关联的属性。当然,您需要做的不仅仅是
Writeln(attr.ToString)
,但这应该会让您了解如何继续。您可以用常规方法测试特定属性

if attr is TMyAttribute then
  ....

值得一提的是,行
ctx:=TRttiContext.Create()根本不需要。你可以愉快地删除它!您的示例代码不完整。提供要用TMyAttribute注释的类。@menjaraz不,这不是必需的。这就是答案。@menjaraz Done:)@DavidHeffernan在这种情况下不需要
Create
,但如果我使用ctx几次,就不需要保存旧的上下文数据,所以我更喜欢
Create
始终保存它(:@teran无论发生什么,它都是按需创建的,因此如果你想清除旧的,那么在完成后调用
Free
。我个人发现这种风格(如Embarcadero所示)让记录看起来像类是一种误导。我希望他们不要在记录中使用
Create
Free
,因为它使代码的读取器知道
ctx
是一种堆分配的引用类型。它绝不是。