I’m working on a class TMethodsInjector that uses RTTI to inject a method into a method-type property (like events). If a method is already assigned, I want to combine it with the new one (same signature) and assign the result.
The key part is here:
if not Assigned(LOldMethod.Code) then
LCombined := LNewMethod
else
LCombined := GenerateCombinedMethod(LRttiProperty, LOldMethod, LNewMethod);
I need help implementing GenerateCombinedMethod — it should dynamically wrap both LOldMethod and LNewMethod (same structure) into a single TMethod that invokes both in order.
Is there a clean way to do this using RTTI, without knowing the method signature in advance?
my full class code is:
unit API.Methods.Injector;
interface
uses
System.Classes,
System.SysUtils,
System.Rtti,
System.TypInfo;
type
TMethodsInjector = class
public
class procedure InjectMethod(aTarget: TObject; const aPropertyName: string;
aMethodAddress: Pointer; aMethodData: TObject); static;
end;
implementation
{ TMethodsInjector }
class procedure TMethodsInjector.InjectMethod(aTarget: TObject; const aPropertyName: string;
aMethodAddress: Pointer; aMethodData: TObject);
var
LRttiContext: TRttiContext;
LRttiType: TRttiType;
LRttiProperty: TRttiProperty;
LOldMethod, LNewMethod, LCombined: TMethod;
begin
if not Assigned(aTarget) then
Exit;
LRttiContext := TRttiContext.Create;
try
LRttiType := LRttiContext.GetType(aTarget.ClassType);
LRttiProperty := LRttiType.GetProperty(aPropertyName);
if Assigned(LRttiProperty) and (LRttiProperty.PropertyType.TypeKind = tkMethod) then
begin
LOldMethod := GetMethodProp(aTarget, aPropertyName);
LNewMethod.Code := aMethodAddress;
LNewMethod.Data := aMethodData;
if not Assigned(LOldMethod.Code) then
LCombined := LNewMethod
else
LCombined := GenerateCombinedMethod(LRttiProperty, LOldMethod, LNewMethod);
SetMethodProp(aTarget, aPropertyName, LCombined);
end
else
raise Exception.CreateFmt('Property %s not found or is not a method on %s',
[aPropertyName, aTarget.ClassName]);
finally
LRttiContext.Free;
end;
end;
end.