sta*_*mik 10 delphi class-helpers delphi-10.1-berlin
我想使用Gabriel Corneanu的jpegex,jpeg.TJPEGImage的类助手.阅读这个和这个,我了解到,超过德尔福西雅图你不能访问私有字段不再像jpegex确实(在下面的例子中FDATA).和David Heffernan提出的VMT一样,远远超出我的范围.有没有更简单的方法来完成这项工作?
type
// helper to access TJPEGData fields
TJPEGDataHelper = class helper for TJPEGData
function Data: TCustomMemoryStream; inline;
procedure SetData(D: TCustomMemoryStream);
procedure SetSize(W,H: integer);
end;
// TJPEGDataHelper
function TJPEGDataHelper.Data: TCustomMemoryStream;
begin
Result := self.FData;
end;
Run Code Online (Sandbox Code Playgroud)
Too*_*the 22
今天我使用with语句找到了解决这个bug的巧妙方法.
function TValueHelper.GetAsInteger: Integer;
begin
with Self do begin
Result := FData.FAsSLong;
end;
end;
Run Code Online (Sandbox Code Playgroud)
此外,Embarcadero做了很好的工作来建造墙壁来保护私人部分,这也许就是为什么他们将它命名为10.1柏林.
Uwe*_*abe 14
谨防!这是一个讨厌的黑客,并且当被黑客类的内部字段结构发生变化时可能会失败.
type
TJPEGDataHack = class(TSharedImage)
FData: TCustomMemoryStream; // must be at the same relative location as in TJPEGData!
end;
// TJPEGDataHelper
function TJPEGDataHelper.Data: TCustomMemoryStream;
begin
Result := TJPEGDataHack(self).FData;
end;
Run Code Online (Sandbox Code Playgroud)
这仅在"hack"类的父类与原始类的父类相同时才有效.因此,在这种情况下,TJPEGData继承自TSharedImage,"hack"类也是如此.位置也需要匹配,所以如果列表中的FData之前有一个字段,那么等效字段应该位于"hack"类中,即使它没有被使用.
有关其工作原理的完整说明,请访问:
通过使用类助手和RTTI的组合,可以使用类助手与以前的Delphi版本具有相同的性能.
诀窍是使用RTTI解决启动时私有字段的偏移量,并将其作为类var存储在帮助程序中.
type
TBase = class(TObject)
private // Or strict private
FMemberVar: integer;
end;
type
TBaseHelper = class helper for TBase // Can be declared in a different unit
private
class var MemberVarOffset: Integer;
function GetMemberVar: Integer;
procedure SetMemberVar(value: Integer);
public
class constructor Create; // Executed automatically at program start
property MemberVar : Integer read GetMemberVar write SetMemberVar;
end;
class constructor TBaseHelper.Create;
var
ctx: TRTTIContext;
begin
MemberVarOffset := ctx.GetType(TBase).GetField('FMemberVar').Offset;
end;
function TBaseHelper.GetMemberVar: Integer;
begin
Result := PInteger(Pointer(NativeInt(Self) + MemberVarOffset))^;
end;
procedure TBaseHelper.SetMemberVar(value: Integer);
begin
PInteger(Pointer(NativeInt(Self) + MemberVarOffset))^ := value;
end;
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它需要一些额外的打字,但与修补整个单元相比,它很简单.