Scan all classes for a given custom attribute

ぃ、小莉子 提交于 2020-01-01 17:28:06

问题


I'm looking for a way of scanning all loaded classes for classes which contain a custom attribute, if possible, without using RegisterClass().


回答1:


at first you have to create TRttiContext, then get all loaded classes using getTypes. after that you can filter types by TypeKind = tkClass; next step is to enumerate attributes and check if it has your attribute;

attribute and test-class delcaration:

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.

and then find it:

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.

output is Unit3.TTest

Call RegisterClass to register a class with the streaming system.... Once classes are registered, they can be loaded or saved by the component streaming system.

so if you don't need component streaming (just find classes with some attribute), there is no need to RegisterClass




回答2:


You can use the new RTTI functionality exposed by the Rtti unit.

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;

This code enumerates attributes associated with methods, properties and fields, as well as with types. Naturally you will want to do more than Writeln(attr.ToString), but this should give you an idea for how to proceed. You can test for your specific attribute in the normal way

if attr is TMyAttribute then
  ....


来源:https://stackoverflow.com/questions/9495952/scan-all-classes-for-a-given-custom-attribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!