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
Teşekkürler Tuğrul Bey.
Weaver bizi uykusuz bırakacak gibi
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
asil uykusuz geceler genisletilen bu rtti desteginden sonra ortaya spring framework tadinda delphi icin de benzer frameworkler yazildigi zaman baslayacak
Cehalet başa bela
Bu spring fw de ne ola, yenir mi içilir mi
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”
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
Veli kardesim onemli degil , helal olsun. tesekkur icin de tesekkur ederim
String integer vb.. gibi tipler için Variant idare ediyordu da. referans tipler için olmuyordu tabiki. 10 Puan
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/