问题
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