Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- unit AssignOperator;
- interface
- uses
- Generics.Collections,
- TypInfo;
- type
- TAssignOperators = record
- private
- type
- TCopyRecord = procedure (dest, source, typeInfo: Pointer);
- TAssignOperator = procedure(left, right: Pointer);
- class var fOperators: TDictionary<PTypeInfo,TAssignOperator>;
- class var fCopyRecord: TCopyRecord;
- class procedure CopyRecordIntercept(dest, source: Pointer; typeinfo: PTypeInfo); static;
- class constructor Create;
- class destructor Destroy;
- public
- class function GetOperator(typeInfo: PTypeInfo): TAssignOperator; static;
- end;
- implementation
- uses
- DDetours,
- Rtti;
- function GetCopyRecordAddress: Pointer;
- asm
- {$IFDEF CPUX64}
- mov rax,offset System.@CopyRecord
- {$ELSE}
- mov eax,offset System.@CopyRecord
- {$ENDIF}
- end;
- class procedure TAssignOperators.CopyRecordIntercept(dest, source: Pointer;
- typeinfo: PTypeInfo);
- var
- assignOperator: TAssignOperator;
- begin
- fCopyRecord(dest, source, typeInfo);
- assignOperator := GetOperator(typeInfo);
- if Assigned(assignOperator) then
- assignOperator(dest, source)
- end;
- class constructor TAssignOperators.Create;
- begin
- fOperators := TDictionary<PTypeInfo,TAssignOperator>.Create;
- fCopyRecord := InterceptCreate(GetCopyRecordAddress, @CopyRecordIntercept)
- end;
- class destructor TAssignOperators.Destroy;
- begin
- InterceptRemove(@fCopyRecord);
- fOperators.Free;
- end;
- class function TAssignOperators.GetOperator(
- typeInfo: PTypeInfo): TAssignOperator;
- var
- context: TRttiContext;
- recordType: TRttiType;
- method: TRttiMethod;
- parameters: TArray<TRttiParameter>;
- begin
- if not fOperators.TryGetValue(typeInfo, Result) then
- begin
- recordType := context.GetType(typeInfo);
- for method in recordType.GetMethods do
- begin
- if (method.Name = 'Assign') and method.IsClassMethod then
- begin
- parameters := method.GetParameters;
- if Length(parameters) = 2 then
- begin
- if (parameters[0].ParamType.Handle = typeInfo)
- and (parameters[1].ParamType.Handle = typeInfo)
- and (pfVar in parameters[0].Flags)
- and (pfVar in parameters[1].Flags) then
- begin
- Result := method.CodeAddress;
- fOperators.AddOrSetValue(typeInfo, Result);
- Exit;
- end;
- end;
- end;
- end;
- end;
- end;
- initialization
- // just make sure the class is used once the unit is used somewhere
- if Assigned(TypeInfo(TAssignOperators)) then;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement