Delphi 2010 (Weaver) ve TValue
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
Veli BOZATLI
on Ağustos 11th, 2009
Teşekkürler Tuğrul Bey.
Weaver bizi uykusuz bırakacak gibi
Tuğrul HELVACI
on Ağustos 11th, 2009
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
sadettinpolat
on Ağustos 11th, 2009
asil uykusuz geceler genisletilen bu rtti desteginden sonra ortaya spring framework tadinda delphi icin de benzer frameworkler yazildigi zaman baslayacak
Tuğrul HELVACI
on Ağustos 12th, 2009
Cehalet başa bela
Bu spring fw de ne ola, yenir mi içilir mi
Veli BOZATLI
on Ağustos 12th, 2009
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”
sadettinpolat
on Ağustos 12th, 2009
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
sadettinpolat
on Ağustos 12th, 2009
Veli kardesim onemli degil , helal olsun. tesekkur icin de tesekkur ederim
Özkan Danacı
on Ekim 21st, 2009
String integer vb.. gibi tipler için Variant idare ediyordu da. referans tipler için olmuyordu tabiki. 10 Puan
sadettinpolat
on Ekim 27th, 2009
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/