Delphi 2010 (Weaver) ve TValue

// 10 Ağustos 2009 // Delphi

Hayatimiz boyunca kim bilir kac defa Showmessage komutunu kullandik ve kim bilir kac defa IntToStr , DateToStr , TimeToStr gibi komutlari kullanarak gostermek istedigimiz degeri string tipine donusturup islemi gerceklestirdik. Bu durumdan kurtulmanin elbet bazi yollari mevcuttu , showmessage komutunu overload etmek , variant tipini kullanmak vs. Bunlardan kimisi delphi icinde standart olmadigindan astari yuzunden pahali olan cozumlerdi kimiside yavasliklari nedeniyle tercih edilmiyordu ve bizde en basit islemlerde bile tip cevrimlerini manuel yaparak yolumuza devam etmek zorunda kaliyorduk.

Overload ifadesi gecmisken asagidaki yaziya da goz atmanizi tavsiye ederim.
http://tr.delphipeak.com/2007/08/30/overload-metodlar.htm

Delphi 2010 ile birlikte genisletilmis bir RTTI (Run-Time Type Information) destegi bizi bekliyor. Tabi bicok seyde oldugu gibi bu ozelliginde bir iyi tarafi var bir de kotu tarafi. Kotu tarafi kodlarinizin decompile edilmesi eskiye nazaran biraz daha kolay olacak iyi tarafi ise calisma zamaninda nesneler hakkinda artik daha fazla bilgi edinebilecegiz ve bu da bize normalde yapilmasi mumkun olmayan ya da bircok taklalar atmamiza neden olacak isleri artik cok kolay bir sekilde yapabilmemizi saglayacak. Kotu tarafi ile ilgili olarak soyleyebilecegimiz iyi haber ise delphinin bu ozelliginin istege bagli olmasi. Yani istersek bu ozelligi kapatabiliyoruz.

{$RTTI EXPLICIT METHODS([]) FIELDS([]) PROPERTIES([])}

Bu ozellik sayesinde yapabileceklerimiz oldukca genis ama bir iki tane ornek vermek gerekirse en basitindan AOP (Aspect Oriented Programming ) uygulamak isterseniz bu cok basit bir sekilde yapabilirsiniz artik ya da tipini bilmediginiz bir degiskeni bir metoda gonul rahatligi ile gonderebilirsiniz. Tip cevrimleriyle ugrasmak yerine degiskenin tipini delphi calisma zamaninda kendi belirlesin.

Simdi bu degiskenin degerinin calisma zamaninda nasil belirlendigine soyle bir bakalim.

TValue adinda Record olarak tanimlanmis yeni bir yapimiz mevcut Delphi 2010 da. TValue kendisine gonderdigimiz degiskenin tipini calisma zamaninda belirleme gibi ozellikleri icerisinde barindiriyor.

function TValue.ToString: string;
begin
  if IsEmpty then
    Exit('(empty)'); // do not localize

  case FData.FTypeInfo^.Kind of
    tkUnknown: Result := '(unknown)'; // do not localize
    tkInteger: Result := IntToStr(AsInt64);
    tkChar: Result := string(AsType);
    tkEnumeration: Result := GetEnumName(FData.FTypeInfo, FData.FAsSLong);
    tkFloat:
      case GetTypeData(FData.FTypeInfo)^.FloatType of
        ftSingle: Result := FloatToStr(FData.FAsSingle);
        ftDouble: Result := FloatToStr(FData.FAsDouble);
        ftExtended: Result := FloatToStr(FData.FAsExtended);
        ftComp: Result := IntToStr(FData.FAsSInt64);
        ftCurr: Result := CurrToStr(FData.FAsCurr);
      end;
    tkString, tkLString, tkUString, tkWString: Result := AsType;
    tkSet: Result := SetToString(FData.FTypeInfo, FData.FAsSLong, True);
    tkClass:
      if FData.FAsObject = nil then
        Result := '(empty)' // do not localize
      else
        Result := Format('(%s @ %p)', [AsObject.ClassName, Pointer(AsObject)]);
      
    tkMethod: Result := Format('(method code=%p, data=%p)', [FData.FAsMethod.Code, FData.FAsMethod.Data]); // do not localize
    tkWChar: Result := AsType;
    tkVariant: Result := '(variant)'; // do not localize
    tkArray: Result := '(array)'; // do not localize
    tkRecord: Result := '(record)'; // do not localize
    tkPointer: Result := Format('(pointer @ %p)', [Pointer(FData.FAsSLong)]); // do not localize
    tkInterface: Result := Format('(interface @ %p)', [Pointer(FData.FHeapData)]); // do not localize
    tkInt64:
      with GetTypeData(FData.FTypeInfo)^ do
        if MinInt64Value > MaxInt64Value then
          Result := UIntToStr(FData.FAsUInt64)
        else
          Result := IntToStr(FData.FAsSInt64);
    tkDynArray: Result := '(dynamic array)'; // do not localize
    tkClassRef:
      if FData.FAsClass = nil then
        Result := '(empty)' // do not localize
      else
        Result := Format('(class ''%s'' @ %p)', [FData.FAsClass.ClassName, Pointer(FData.FAsClass)]); // do not localize
  end;
end;

Eger bir metod TValue tipinde bir parametre aliyorsa biz bu metoda string , integer , obje , tarih gibi bir cok degeri tip cevrimine gerek kalmadan gonderebiliyoruz artik ve gonderdigimiz parametrenin tipini TValue kendisi belirliyor, uygun olan sekilde geriye degerini donderiyor. Kucuk bir ornek yapalim.

  function DegerYaz(Value: TValue): string;
  begin
    Result := Value.ToString;
  end;

seklinde bir metodumuz olsun. Aldigi parametreye dikkat ederseniz TValue tipinde. Bu metoda gonderecegimiz her turlu veri tipi gecerlidir. ToString metodu ise bize gonderdigimiz veri tipine uygun olan string ifadeyi tespit edip geri donderecektir.

program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes,
  Rtti; // --> TValue recordunun tanimlandigi unit.

function DegerYaz(Value: TValue): string;
begin
  result := Value.ToString;
end;

var
  SL: TStringList;
  Obje: TObject;
  Dizi: array of string;
  tarih: TDate;

begin
  try
    tarih := now;
    SL := TStringList.Create;
    SL.Add('1');
    SL.Add('2');
    SL.Add('3');
    Obje := TObject.Create;
    SetLength(Dizi, 2);
    Dizi[0] := 'delphi';
    Dizi[0] := '2010';
    Dizi[0] := 'super';
    tarih := tarih + 1;
    writeln(DegerYaz('string ifade'));
    writeln(DegerYaz(1));
    writeln(DegerYaz(True));
    writeln(DegerYaz(SL));
    writeln(DegerYaz(Obje));
    writeln(DegerYaz(tarih));
    readln;
  except
    on E: Exception do
      writeln(E.ClassName, ': ', E.message);
  end;

end.

bu programin consola ciktisi ise su sekilde olacaktir.

string ifade
1
True
(TStringList @ 00A4DB00)
(TObject @ 00A30D30)
40036,9031108912)

Kod yazma aliskanligizi koklu bir sekilde degistirmeye aday olan TValue cok yakinda aramizda olacak :)

“Delphi 2010 (Weaver) ve TValue” için 9 Yorum

  1. Veli BOZATLI diyor ki:

    Teşekkürler Tuğrul Bey.
    Weaver bizi uykusuz bırakacak gibi :P

  2. Tuğrul HELVACI diyor ki:

    Sadettin ellerine sağlık, Weaver’ı bekliyoruz dört gözle. Veli bey, makale Sadettin arkadaşımıza aittir, onun el emeği göz nuru ;)

  3. sadettinpolat diyor ki:

    asil uykusuz geceler genisletilen bu rtti desteginden sonra ortaya spring framework tadinda delphi icin de benzer frameworkler yazildigi zaman baslayacak :)

  4. Veli BOZATLI diyor ki:

    Kusura bakmayın; “Posted by sadettinpolat” mış, hiç dikkat etmemiştim.
    Sadettin Bey hakkınızı helal ediniz.
    Tuğrul Bey’den teşekkürü geri almadan size yeni bir tane veriyorum “Teşekkürler” :)

  5. sadettinpolat diyor ki:

    Spring aslinda icerisinde epey ozellik barindiran bir java frameworku ama bizim daha cok ilgilendigimiz Inversion of Control / Dependency Injection prensibleri. ihtiyacimiz olan nesnelerin tum bilgilerine run time da erisebildigimiz icin nesneler arasindaki bazi iliskileri olusturma gorevini bizden bagimsiz bir yapiya devredip biz enerjimizi daha fakli sorunlar icin harcayabiliriz.

    Mesela veritabanindan bir tablodaki bilgileri okuyacak bir sinifa ihtiyacimiz olsun. gerekli metod ve sql leri yazdiktan sonra bir de bu sinifin veritabanina erisebilmesi icin bu sinifa TQuery tarzinda bir sinif vermemiz lazim. Bu durum hem nesnemizle TQuery arasinda bir bagimliliga neden oluyor hem de TQuery yi olusturma isi de biz programcilara kaliyor. Spring burda devreye girip bizim TQuery sinifindan bir ornege ihtiyacimiz oldugunu bilip bi tane TQuery sinifindan ornek olusturup bizim sinifin icerisine enjekte ediyor. Hem bagimlilik azalmis hem de hamalliktan kurtulmus oluyoruz :)

    http://analystdeveloper.com/blogs/gurkan/archive/2006/03/19/3056.aspx

  6. sadettinpolat diyor ki:

    Veli kardesim onemli degil , helal olsun. tesekkur icin de tesekkur ederim :)

  7. Özkan Danacı diyor ki:

    String integer vb.. gibi tipler için Variant idare ediyordu da. referans tipler için olmuyordu tabiki. 10 Puan :)

  8. sadettinpolat diyor ki:

    yukarida spring frameworkten bahsetmis ve bu tip frameworklerin delphi 2010 ile birlikte artik kolay bir sekilde gelistirilebileceginden bahsetmistik.

    cinli bir arkadasimiz kollari sivamis. umarim tez zamanda biter :)

    http://code.google.com/p/delphi-spring-framework/

Yorum Yazın