Delphi 重新调整实例类内存分配的大小
我在运行时将此示例用于Change类:Delphi 重新调整实例类内存分配的大小,delphi,class,instance,Delphi,Class,Instance,我在运行时将此示例用于Change类: procedure PatchInstanceClass(Instance: TObject; NewClass: TClass); type PClass = ^TClass; begin if Assigned(Instance) and Assigned(NewClass) and NewClass.InheritsFrom(Instance.ClassType) and (NewClass.InstanceSize = In
procedure PatchInstanceClass(Instance: TObject; NewClass: TClass);
type
PClass = ^TClass;
begin
if Assigned(Instance) and Assigned(NewClass)
and NewClass.InheritsFrom(Instance.ClassType)
and (NewClass.InstanceSize = Instance.InstanceSize) then
begin
PClass(Instance)^ := NewClass;
end;
end;
type
TMyButton = class(TButton)
Private
FLogEvent : TNotifyEvent;
public
Property Log : TNotifyEvent Read FLogEvent Write FLogEvent;
procedure Click; override;
end;
procedure TMyButton.Click;
begin
Inherited;
if Assigned(FLogEvent) then
FLogEvent(Self);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
PatchInstanceClass(Button1, TMyButton);
end;
我的问题是TMyButton的大小与TButton不同,因为我将此事件添加到TMyButton中。
我的问题是如何重新调整NewClass同一实例的内存分配大小。:-) 你试图做的是不切实际的。如果可以找到对该对象的所有引用,或许可以这样做。您需要这样做,因为重新分配可能会导致内存驻留在不同的地址。因此,您需要更新这些引用 因此,您需要找到:
- 代码中的所有引用,以及
- VCL代码中的所有引用李>
- 使用插入器类
- 使用虚拟方法拦截器
- 处理应用程序的OnMessage事件以筛选消息队列
你真的应该放弃目前解决问题的方法。虽然我同意其他人的观点,但你应该重新考虑你的方法,因为这有点老套。然而,我喜欢黑客的东西-所以我要告诉你如何才能实现你的要求 关键是不要在新类中放入任何内容(因为InstanceSize需要相同)将其放在其他地方-如果您使用的是较新的Delphi版本(2010或更高版本),您可以这样做。否则,您需要对代码进行一些修改,但我想您会明白这一点:
uses
Generics.Collections;
procedure PatchInstanceClass(Instance: TObject; NewClass: TClass);
begin
if Assigned(Instance) and Assigned(NewClass)
and NewClass.InheritsFrom(Instance.ClassType)
and (NewClass.InstanceSize = Instance.InstanceSize) then
begin
PPointer(Instance)^ := NewClass;
end;
end;
type
TMyButton = class(TButton)
private
function GetLogEvent: TNotifyEvent;
procedure SetLogEvent(const Value: TNotifyEvent);
public
destructor Destroy; override;
procedure Click; override;
property LogEvent: TNotifyEvent read GetLogEvent write SetLogEvent;
end;
TMyButtonHelper = class helper for TMyButton
private
class var fLogEvents: TDictionary<TObject, TNotifyEvent>;
public
class constructor Create;
class destructor Destroy;
end;
{ TMyButtonHelper }
class constructor TMyButtonHelper.Create;
begin
fLogEvents := TDictionary<TObject, TNotifyEvent>.Create;
end;
class destructor TMyButtonHelper.Destroy;
begin
fLogEvents.Free;
end;
{ TMyButton }
destructor TMyButton.Destroy;
begin
fLogEvents.Remove(Self);
inherited;
end;
procedure TMyButton.Click;
begin
inherited;
if Assigned(LogEvent) then
LogEvent(Self);
end;
function TMyButton.GetLogEvent: TNotifyEvent;
begin
fLogEvents.TryGetValue(Self, Result);
end;
procedure TMyButton.SetLogEvent(const Value: TNotifyEvent);
begin
fLogEvents.AddOrSetValue(Self, Value);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
PatchInstanceClass(Button1, TMyButton);
TMyButton(Button1).LogEvent := Button1Click;
end;
使用
仿制药。收藏;
过程PatchInstanceClass(实例:TObject;新类:TClass);
开始
如果已分配(实例)和已分配(新类)
和NewClass.InheritsFrom(Instance.ClassType)
和(NewClass.InstanceSize=Instance.InstanceSize)然后
开始
PPointer(实例)^:=NewClass;
结束;
结束;
类型
TMyButton=类(TButton)
私有的
函数GetLogEvent:TNotifyEvent;
过程SetLogEvent(常量值:TNotifyEvent);
公众的
毁灭者毁灭;推翻
程序点击;推翻
属性LogEvent:TNotifyEvent read GetLogEvent write SetLogEvent;
结束;
TMyButtonHelper=TMyButton的类帮助器
私有的
分类变量fLogEvents:t字典;
公众的
类构造函数创建;
类析构函数销毁;
结束;
{TMyButtonHelper}
类构造函数TMyButtonHelper.Create;
开始
fLogEvents:=TDictionary.Create;
结束;
类析构函数TMyButtonHelper.Destroy;
开始
免费的;
结束;
{TMyButton}
析构函数TMyButton.Destroy;
开始
絮状物。移除(自身);
继承;
结束;
程序TMyButton。单击;
开始
继承;
如果已分配(LogEvent),则
LogEvent(Self);
结束;
函数TMyButton.GetLogEvent:TNotifyEvent;
开始
fLogEvents.TryGetValue(自身、结果);
结束;
过程TMyButton.SetLogEvent(const值:TNotifyEvent);
开始
fLogEvents.AddOrSetValue(Self,Value);
结束;
过程TForm1.FormCreate(发送方:TObject);
开始
PatchInstanceClass(按钮1,TMyButton);
TMyButton(Button1).LogEvent:=按钮1单击;
结束;
使用interposer类,您不需要任何黑客攻击。您想实现什么?这是错误的解决方案,概率>0.999。您不应该这样做,因为调整对象实例的大小通常会重新定位内存中的实例,并使对实例的引用无效。最好在这样做时使用虚拟方法拦截器this@Farzad问题不是问了如何重新调整实例的大小吗?