Konuyu Paylaş : facebook gplus twitter

Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Sınıfın Private Alanlarına Erişim
#1
unit MyClass;

interface

uses Dialogs,
 SysUtils;

type
 TMyClass = class
 private
   FieldA: Integer;
   FieldB: string;
 public
   constructor Create();
   procedure Test;
 end;

implementation

{ TMyClass }
constructor TMyClass.Create();
begin
 inherited;
 FieldA := 123;
 FieldB := 'TEST';
end;

procedure TMyClass.Test;
begin
 ShowMessage(IntToStr(FieldA));
 ShowMessage(FieldB);
end;

end.

Yukarıdaki Uniti projeye ekledikten sonra, TMyClass sınıfından bir nesne oluşturup, private bölümde bulunan FieldA ve FieldB alanlarına erişerek değerlerinin değiştirilmesi istenmektedir.

Kısıtlamalar:
  1. MyClass unit'inde ve TMyClass sınıfında herhangi bir kod değişikliği yapmak yasak.
  2. TMyClass sınıfından bir alt sınıf (sub class) oluşturmak ve kullanmak yasak.
  3. Class helper vs kullanmak yasak.
Test methodunu çağırdığımızda 123 ve TEST değerleri yerine başka değerler görmemiz gerekiyor.
var
 MyObject: TMyClass;
begin
 MyObject := TMyClass.Create;
 {
   sihirli kodlar buraya yazılacak
 }
 MyObject.Test;
 MyObject.Free;
end;


Kolay gelsin.
My name is nobody.
WWW
Cevapla
#2
var
MyObject: TMyClass;
begin
MyObject := TMyClass.Create;                                //MyObject  nesnesi sınıf elemenlarının adreslerinin tutulduğu adresi tutuyor.
integer(pointer(nativeint((@MyObject)^)+4)^):=65;
//önce MyObject 'in adresine (@),ardından elemanların adreslerinin tutulduğu adrese(^),sonra 1.elemanın adresine(+4) ve nihayet elemanın kendisinine(^) ulaşıyoruz.
string(pointer(nativeint((@MyObject)^)+8)^):='Özel Alan Değişti.';
//önce MyObject 'in adresine (@),ardından elemanların adreslerinin tutulduğu adrese(^),sonra 2.elemanın adresine(+8) ve nihayet elemanın kendisinine(^) ulaşıyoruz.
//Not: Burada elemanın boyutunun bir önemi yok,adresler tutulduğu için 4'er bayt ilerlemek eleman adreslerini dolaşmak anlamına geliyor;çünkü adresler 4 byte değerindedir.
MyObject.Test;
MyObject.Free;
end;
Bizi Toprağa Gömdüler Fakat Tohum Olduğumuzu Bilmiyorlardı.
Cevapla
#3
type

   TMyClassHook = class(TMYClass);

.

.

.

procedure TForm1.Button1Click(Sender: TObject);
var
 a : TMyClass;
begin
 a := TMyClass.Create();
 TMyClassHook(a).FieldA := 1234;
 TMyClassHook(a).FieldB := 'asd';

 Memo1.Lines.Add(a.FieldB);
 Memo1.Lines.Add(IntToStr(a.FieldA));
end;
WWW
Cevapla
#4
var
MyObject : TMyClass;
AValue   : TValue;
begin
MyObject := TMyClass.Create;
AValue := TValue.FromVariant(666);
TRttiContext.Create.GetType(TMyClass).GetField('FieldA').SetValue(MyObject, AValue);
AValue := TValue.FromVariant('DelphiCan');
TRttiContext.Create.GetType(TMyClass).GetField('FieldB').SetValue(MyObject, AValue);
MyObject.Test;
MyObject.Free;
Amatör Küme Bilgisayar Programcısı
WWW
Cevapla
#5
Hakan Bey Yazdığım 2. madde bulunan sub class kullanım kısıtlamasını gözardı etmişsiniz.  Smile 
RTTI kullanımını kısıtlamak aklıma gelmediği için Ali Bey'in cevabı da kabul edilebilir. 
Savaş hocam'ın açıklamaları muazzam. Ben de açık halini paylaşayım.
var
 MyObject: TMyClass;
 P: PByte;
begin
 MyObject := TMyClass.Create;

 P := PByte(MyObject);
 Inc(P, SizeOf(Pointer));
 PINT(P)^ := 321;

 Inc(P, SizeOf(Pointer));
 PString(P)^ := 'XXXX';

 MyObject.Test;
 MyObject.Free;
end;
Zaman ayırıp cevap yazan arkadaşlara teşekkür ederim.
My name is nobody.
WWW
Cevapla
#6
Cevap veren tüm arkadaşların ellerine sağlık. Aynı zamanda bu tarz konuları açan ve destekleyen ismail kardeşime de teşekkür ediyorum.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#7
Internette dolaşırken tesadüfen gördüğüm Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol içerisinde tam da bu soruya uygun bir cevap buldum Smile

Yeni bir sınıf tanımlıyoruz ve bu sefer ulaşmak istediğimiz değerleri public tanımlıyoruz:
TMyClassAccessor = class
public
   FieldA: integer;
   FieldB: string;
end;

Kullanımı:

var
  MyObject: TMyClass;
begin
  MyObject := TMyClass.Create;
  TMyClassAccessor(MyObject).FieldA := 321;
  TMyClassAccessor(MyObject).FieldB := 'TSET';
  MyObject.Test;
  MyObject.Free;
end;
There's no place like 127.0.0.1
WWW
Cevapla

Konuyu Paylaş : facebook gplus twitter





Konuyu Okuyanlar: 1 Ziyaretçi