<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>Diyezon</title> <atom:link href="http://www.diyezon.com/feed/" rel="self" type="application/rss+xml" /><link>http://www.diyezon.com</link> <description>programlama sanatÄ±...</description> <lastBuildDate>Tue, 24 Jan 2012 00:13:26 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>ASP.NET MVC &#8211; View</title><link>http://www.diyezon.com/asp-net-mvc-view/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=asp-net-mvc-view</link> <comments>http://www.diyezon.com/asp-net-mvc-view/#comments</comments> <pubDate>Mon, 23 Jan 2012 23:59:58 +0000</pubDate> <dc:creator>Fatih Tolga Ata</dc:creator> <category><![CDATA[ASP.NET]]></category> <category><![CDATA[MVC]]></category> <category><![CDATA[asp.net]]></category> <category><![CDATA[Child Action]]></category> <category><![CDATA[HtmlHelpers]]></category> <category><![CDATA[Layout]]></category> <category><![CDATA[mvc]]></category> <category><![CDATA[partial view]]></category> <category><![CDATA[Section]]></category> <category><![CDATA[view]]></category> <category><![CDATA[ViewBag]]></category> <category><![CDATA[ViewData]]></category><guid
isPermaLink="false">http://www.diyezon.com/?p=399</guid> <description><![CDATA[ASP.NET MVC yazÄ± dizimize baÅŸladÄ±ÄŸÄ±mÄ±z buradaki makale ile mvc mantÄ±ÄŸÄ±nÄ± anladÄ±k ve View&#8217;in ne olduÄŸunu yÃ¼zeysel olarak Ã¶ÄŸrendik. ASP.NET MVC kullanarak bir web sitesi yapmak istiyorsanÄ±z View&#8217;ler Ã¶ÄŸrenmeniz gereken en Ã¶nemli konulardan birisidir. Bu yazÄ±mÄ±zda MVC mimarisinin sunum kÄ±smÄ± olan View&#8217;leri inceleyeceÄŸiz. View Ä°lk makalemizde bahsettiÄŸimiz gibi View, MVC mimarisinin sunum kÄ±smÄ±dÄ±r. Controller bir action [...]]]></description> <content:encoded><![CDATA[<p
style="text-align: justify;">ASP.NET MVC yazÄ± dizimize baÅŸladÄ±ÄŸÄ±mÄ±z <a
title="ASP.NET MVC ve Razorâ€™a GiriÅŸ" href="http://www.diyezon.com/2011/08/07/asp-net-mvc-ve-razora-giris/" target="_blank">buradaki</a> makale ile mvc mantÄ±ÄŸÄ±nÄ± anladÄ±k ve View&#8217;in ne olduÄŸunu yÃ¼zeysel olarak Ã¶ÄŸrendik. ASP.NET MVC kullanarak bir web sitesi yapmak istiyorsanÄ±z View&#8217;ler Ã¶ÄŸrenmeniz gereken en Ã¶nemli konulardan birisidir.</p><p
style="text-align: justify;">Bu yazÄ±mÄ±zda MVC mimarisinin sunum kÄ±smÄ± olan View&#8217;leri inceleyeceÄŸiz.</p><p><span
id="more-399"></span></p><h1>View</h1><p
style="text-align: justify;">Ä°lk makalemizde bahsettiÄŸimiz gibi <em>View</em>, MVC mimarisinin sunum kÄ±smÄ±dÄ±r. Controller bir action metodu iÅŸletikten sonra, kullanÄ±cÄ± tarafÄ±na bir ÅŸeyler gÃ¶stermesi gerekmektedir. Tabi View kullanmasÄ± zorunlu olmasa da genelde Controller, o action metoda ait bir View, yine zorunlu olmasa da bir model aracÄ±lÄ±ÄŸÄ± ile verileri alarak kullanÄ±cÄ±ya iletir. Burada bilmemiz gereken en Ã¶nemli nokta View&#8217;ler Controller ve Model&#8217;ler gibi Ã¶nceden derlenmiÅŸ bir dll iÃ§inde deÄŸillerdir ve <strong>dinamik</strong> olarak derlenirler. KÄ±saca ÅŸematize edecek olursak:</p><div
id="attachment_434" class="wp-caption aligncenter" style="width: 627px"><img
class="size-full wp-image-434" title="MVC Ã‡alÄ±ÅŸma DiyagramÄ±" src="http://www.diyezon.com/wp-content/uploads/2012/01/Drawing1.png" alt="MVC Ã‡alÄ±ÅŸma DiyagramÄ±" width="617" height="372" /><p
class="wp-caption-text">MVC Ã‡alÄ±ÅŸma DiyagramÄ±</p></div><p
style="text-align: justify;">Tabi gerÃ§ek bir sitede durumlar daha da karmaÅŸÄ±k olabilir. Diyagrama bakacak olursak, gelen kulanÄ±cÄ± isteÄŸinin nasÄ±l iÅŸlenip View&#8217;lere iletildiÄŸini gÃ¶rmÃ¼ÅŸ olacaÄŸÄ±z. Her action metod farklÄ± biÃ§imlerde View&#8217;lere eriÅŸmektedir. Kimisi herhangi bir model yapÄ±sÄ± kullanmadan direk olarak, kimisi model kullanarak, kimisi de entity ya da baÅŸka bir veritabanÄ± sÄ±nÄ±fÄ±nÄ± model olarak kullanarak View&#8217;ler ile kullanÄ±cÄ±nÄ±n karÅŸÄ±sÄ±na Ã§Ä±kmaktadÄ±r.</p><p
style="text-align: justify;">Ã–nceden de bahsettiÄŸimiz gibi, View&#8217;e kadar olan bÃ¼tÃ¼n kÄ±sÄ±mlar Ã¶nceden derlenmiÅŸ assembly dll dosyalarÄ± iÃ§inde bulunmakta ve View kÄ±smÄ± ise kullanÄ±cÄ± istekte bulunduÄŸunda <strong>dinamik</strong> olarak derlenmektedir. Bu yÃ¼zden siteniz sunucuya atÄ±lÄ±rken View dosyalarÄ± (Razor iÃ§in cshtml ya da vbhtml) olduÄŸu gibi atÄ±lÄ±rlar. Bununla birlikte dinamik derleme olduÄŸundan dolayÄ±, View dosyalarÄ± iÃ§inde sunucu kodlarÄ±na ait Ã§ok fazla kod bulunmamasÄ± iyi olur. Genelde View dosyalarÄ±nda kontrol yapÄ±larÄ±(switch case, if..) ve dÃ¶ngÃ¼ler(for, while) gibi basit kodlar bulunmalÄ±. Daha karmaÅŸÄ±k iÅŸlemleri Controller iÃ§inde halletmeli ve sonucu View&#8217;e yollamalÄ±yÄ±z. BurasÄ± Ã¶nemli bir nokta idi. AyrÄ±ca her ne kadar View iÃ§inden veritabanÄ±na da eriÅŸbilseniz de bu yapmamanÄ±z gereken bir iÅŸlem olacaktÄ±r. VeritabanÄ± iÅŸlemlerinizi de Controller iÃ§inde yapmalÄ±sÄ±nÄ±z.</p><p
style="text-align: justify;">MVC&#8217;de bir action metoda ait view&#8217;i Ã§aÄŸÄ±rmak iÃ§in metod sonundan ÅŸu ÅŸekilde Ã§Ä±kÄ±ÅŸ saÄŸlarÄ±z:</p><pre>
<pre class="brush: csharp">
public ActionResult ActionMethod1()
{
    return View();
}
</pre></pre><p
style="text-align: justify;">EÄŸer bu action metod&#8217;a ait herhangi bir View dosyasÄ± oluÅŸturmaz ve bu kodu Ã§alÄ±ÅŸtÄ±rÄ±rsanÄ±z, MVC sistemi size bu action&#8217;a ait View&#8217;Ä± nerelerde arayÄ±p da bulamadÄ±ÄŸÄ±na dair bir hata mesajÄ± gÃ¶sterecektir. Bu hata mesajÄ±na dikkat ederseniz varsayÄ±lan konumlar ilk baÅŸta View klasÃ¶rÃ¼nde Controller ile<strong> aynÄ± isimde</strong> bir klasÃ¶r iÃ§indeki bir cshtml dosyasÄ±dÄ±r. Bu dosya, view&#8217;Ä± Ã§aÄŸÄ±rdÄ±ÄŸÄ±mÄ±z action metod ile <strong>aynÄ± isme</strong> sahiptir. YukarÄ±daki Ã¶rnek iÃ§in bu dosya ActionMehod1.cshtml olacaktÄ±r.</p><p
style="text-align: justify;"><em>View()</em> metoduile baÅŸka baÅŸka view&#8217;ler de Ã§aÄŸrÄ±labilir. Mesela <em>BaskaBirView</em> gibi bir View dosyasÄ±nÄ± Ã§aÄŸÄ±rmak iÃ§in <em>View(&#8220;BaskaBirView&#8221;)</em> ÅŸeklinde parametre vermeliyiz.</p><p
style="text-align: justify;">Åžimdi basit bir view dosyasÄ±nÄ± incelemek iÃ§in ufak bir Ã¶rnek yapalÄ±m. VS ya da VWD&#8217;de yeni bir MVC projesi aÃ§alÄ±m. View engine olarak Razor&#8217;u seÃ§elim. Template olarak Empty seÃ§elim ve formu onaylayÄ±p kapatalÄ±m. KarÅŸÄ±mÄ±za boÅŸ bir MVC projesi gelecektir. Solution Explorer&#8217;dan Controller klasÃ¶rÃ¼ne saÄŸ tuÅŸla tÄ±klayÄ±p Add alt menÃ¼sÃ¼nden Controller seÃ§eneÄŸini seÃ§elim. Ä°sim olarak <strong>HomeController</strong> girelim.Â  KarÅŸÄ±mÄ±za <em>HomeController</em> iÃ§indeki Ã¶nceden eklenmiÅŸ bir bir action metod gelecektir. Åžimdilik ismini Index olarak bÄ±rakalÄ±m ve deÄŸiÅŸtirmeyelim. Bu metodun herhangi bir yerinde(iÃ§inde, isminin Ã¼zerinde, vs..) saÄŸ tuÅŸla tÄ±klayÄ±p Add View seÃ§eneÄŸini seÃ§elim. KarÅŸÄ±mÄ±za gelecek olan pencere bir MVC projesinde Ã§okca karÅŸÄ±laÅŸacaÄŸÄ±mÄ±z bir penceredir. KÄ±saca buradaki seÃ§eneklerden bahsedecek olursak;</p><p
style="text-align: justify;"><strong>&#8220;View engine&#8221;</strong>: Bu seÃ§enek, varsayÄ±lan olarak proje iÃ§in belirlediÄŸiniz gÃ¶rÃ¼nÃ¼m motoru ayarlÄ± olarak gelecektir. Bizim iÃ§in bu seÃ§enek tabi ki Razor olacaktÄ±r.</p><p
style="text-align: justify;"><strong>&#8220;Create a strongly typed view&#8221;</strong>: Bu seÃ§enek ile Ã¶nceden projeye dahil etmiÅŸ olduÄŸumuz bir modeli, View&#8217;e model olarak tanÄ±tÄ±yoruz. Yani view nesnemize bir modeli dayatmÄ±ÅŸ oluyoruz. YalnÄ±z unutmamanÄ±z gereken ÅŸey, bu listede yeni eklediÄŸiniz modellerinizin gÃ¶rÃ¼nmesini istiyorsanÄ±z projeyi bir kez <strong>derlemeyi</strong> unutmamanÄ±z gerekmektedir.</p><p
style="text-align: justify;"><strong>&#8220;Scaffold template&#8221;</strong>: Bir proejde, Ã¶zellik yÃ¶netim kÄ±smÄ±nda ekleme, silme, dÃ¼zenleme gibi bir iÅŸlemler iÃ§in elimizle tek tek view oluÅŸturmak yerine, buradaki template&#8217;leri seÃ§erek daha hÄ±zlÄ± bir Ã§ekilde bu viewleri oluÅŸturabiliriz.</p><p
style="text-align: justify;"><strong>&#8220;Create as a partial view&#8221;</strong>: Bu seÃ§enek ile view dosyamÄ±zÄ±n bir partial view olduÄŸunu belirtmiÅŸ oluyoruz. Bu konu bir kaÃ§ baÅŸlÄ±k sonra karÅŸÄ±nÄ±za gelecek. Bu yÃ¼zden bu ksÄ±mÄ± geÃ§iyoruz ve boÅŸ bÄ±rakÄ±yoruz.</p><p
style="text-align: justify;"><strong>&#8220;Use a layout or master page&#8221;</strong>: Buradan Layout dosyamÄ±zÄ± belirliyoruz. Bu konuya da daha sonra deÄŸineceÄŸiz. BurayÄ± seÃ§ili ama boÅŸ bÄ±rakÄ±n.</p><p
style="text-align: justify;">Bu formu onaylayÄ±p kapattÄ±ÄŸÄ±nÄ±zda boÅŸ bir view dosyasÄ± ile karÅŸÄ± karÅŸÄ±ya geleceÄŸiz. View dosyamÄ±zÄ± incelemeden Ã¶nce Solution Explorer&#8217;dan Models klasÃ¶rÃ¼ altÄ±na yeni bir sÄ±nÄ±f ekleyelim ve ismine <em>BirModel</em> girelim. ArdÄ±ndan aÅŸaÄŸÄ±daki gibi kodlarÄ±nÄ± deÄŸiÅŸtirelim:</p><pre>
<pre class="brush: csharp">public class BirModel
{
Â Â Â  public List&lt;int&gt; Liste { get; set; }
}</pre></pre><p
style="text-align: justify;">Åžimdi projemizi bir kez derleyelim ve View dosyamÄ±zÄ± da ÅŸu ÅŸekilde deÄŸiÅŸtirelim:</p><pre>
<pre class="brush: csharp">@model MvcArticle3_1.Models.BirModel
@{
Â Â Â  ViewBag.Title = &quot;Ana sayfa&quot;;
}

&lt;ul&gt;
@foreach (int sayi in Model.Liste)
{
Â Â Â  &lt;li&gt;@sayi&lt;/li&gt;
}
&lt;/ul&gt;</pre></pre><p
style="text-align: justify;">Åžimdi bir sonraki adÄ±ma geÃ§meden Ã¶nce buradaki kodlara bir gÃ¶z atalÄ±m.</p><p
style="text-align: justify;">Ä°lk satÄ±rda view dosyamÄ±za bir model dayatmÄ±ÅŸ olduk. View oluÅŸtururken karÅŸÄ±mÄ±za gelen form&#8217;da <strong>&#8220;Strongly typed view&#8221;</strong> ile de seÃ§ebileceÄŸimiz bir model ile view dosyamÄ±zÄ±n kullanacaÄŸÄ± model&#8217;i belirlemiÅŸ oluyoruz. Burada model belirlenirken, model&#8217;in tam yolunu belirtmemiz gerekiyor. Ben projeye <em>MvcArticle3_1</em> gibi garip bir isim verdiÄŸimden dolayÄ± ana namespace olarak bu gÃ¶zÃ¼kÃ¼yor. Ama siz buraya kendi projenize gÃ¶re bir namespace&#8217;i giremlisiniz. Yani kÄ±sacasÄ±, model&#8217;in namespace&#8217;i ile beraber tam yolunu belirtmeniz gerekmetkedir.</p><p
style="text-align: justify;">Daha sonraki gelen, 3 satÄ±rdan oluÅŸan blok ile sayfamÄ±zÄ±n baÅŸlÄ±ÄŸÄ± belirleniyor. Buradaki <em>ViewBag</em> ve <em>ViewBag.Title</em> ayrÄ±ntÄ±sÄ±na sonra deÄŸineceÄŸiz. SonrasÄ±nda gelen <em>foreach</em> dÃ¶ngÃ¼sÃ¼ ile <em>BirModel</em> isimli modelimizde bulunan Liste ismindeki <em>List&lt;int&gt;</em> dizisini kullanÄ±yoruz. Dikkat ederseniz bir view&#8217;e ait modeli kullanabilmek iÃ§ni Model deÄŸiÅŸkenini kullanÄ±yoruz.</p><p
style="text-align: justify;">Buraya kadar her ÅŸey gÃ¼zel. Åžimdi bu view dosyamÄ±zÄ± Ã§alÄ±ÅŸÄ±r hale getirmek iÃ§in Controller sÄ±nÄ±fÄ±mÄ±zda bir kaÃ§ satÄ±rÄ± dÄŸiÅŸtireceÄŸiz. <em>Index</em> action metodunu aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim:</p><pre>
<pre class="brush: csharp">public ActionResult Index()
{
    var birModel = new BirModel
Â Â Â  {
Â Â Â Â     Liste = new List&lt;int&gt; { 1,39,4,744 }
Â Â Â  };

Â Â Â  return View(birModel);
}</pre></pre><p
style="text-align: justify;">Projeyi derleyip Ã§alÄ±ÅŸtÄ±rdÄ±ÄŸÄ±mÄ±zda <em>&lt;ul&gt; , &lt;li&gt;</em> &#8216;den oluÅŸan Ã§Ä±ktÄ±mÄ±zÄ± gÃ¶rebilirsiniz.</p><p
style="text-align: justify;">Åžimdi farklÄ± bir ÅŸey yapacaÄŸÄ±z ve bu view dosyamÄ±zÄ±n derlenmiÅŸ haline gÃ¶z atacaÄŸÄ±z. <strong>&#8220;C:\Windows\Microsoft.NET\Framework&#8221;</strong> klasÃ¶rÃ¼ne girelim ve buradan kullandÄ±ÄŸÄ±mÄ±z .net versiyonunun klasÃ¶rÃ¼ne girelim(makale yazÄ±lÄ±rken 4.0* idi). Bu klasÃ¶rde <strong>&#8220;Temporary ASP.NET Files&#8221;</strong> isminde bir klasÃ¶r gÃ¶receksiniz. Bu klasÃ¶r altÄ±nda bulunan root klasÃ¶rÃ¼ne girelim ve explorer&#8217;dan dosyalarÄ± deÄŸiÅŸtirme tarihine gÃ¶re sÄ±ralayalÄ±m. En Ã¼steki klasÃ¶re girelim ve <strong>&#8220;App_Web_index.cshtml.*.cs&#8221;</strong> ismindeki dosyayÄ± bir editÃ¶r ile aÃ§alÄ±m. Buradaki * deÄŸiÅŸken bir hash deÄŸeridir.</p><p
style="text-align: justify;">View dosyamÄ±z ile (Index.cshtml) derlenme esnasÄ±nda oluÅŸturulmuÅŸ olan bu dosyayÄ± karÅŸÄ±laÅŸtÄ±ralÄ±m. Ã–nceden de bahsettiÄŸimiz gibi ASP.NET MVC, view dosyalarÄ±nÄ± <strong>dinamik</strong> olarak derler. Fakat view dosyasÄ± <strong>deÄŸiÅŸtirilmemiÅŸ</strong> ise Ã¶nceden derlenmiÅŸ olan halini kullanÄ±r ve tekrar derleme gafletinde bulunmaz. Buradaki dosyada da gÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi bÃ¼tÃ¼n html bilgileri <em>WriteLiteral</em> fonksiyonu ile sarÄ±lmÄ±ÅŸ durumdalar. Razor&#8217;un @ iÅŸareti ile belirttiÄŸiniz c# kodlarÄ± ise direk olarak bu dosyaya dahil edilmiÅŸtir. View&#8217;in Ã§alÄ±ÅŸma mantÄ±ÄŸÄ±nÄ± anlamak iÃ§in bu karÅŸÄ±laÅŸtÄ±rmayÄ± yapmanÄ±z Ã¶nemli. Ã–zellikle baÅŸka Razor gramerleri ile Ã¼retilen sonuca da gÃ¶z atabilirsiniz. AynÄ± klasÃ¶rde &#8220;App_Web_*.dll&#8221; gibi bir kaÃ§ derlenmiÅŸ assembly dosyasÄ± bulacaksÄ±nÄ±z. Bu dosyayÄ± reflector ya da VWD iÃ§indeki object browser ile aÃ§abilirsiniz. Bu assembly&#8217;de gÃ¶receÄŸiniz gibi Index.cshtml dosyamÄ±z, dinamik olarak derlenerek bu dll altÄ±na bir <strong>sÄ±nÄ±f</strong> olarak yerleÅŸmiÅŸtir. Bir dahaki Index.cshtml dosyasÄ± Ã§aÄŸrÄ±ldÄ±ÄŸÄ±nda, view dosyasÄ± eÄŸer deÄŸiÅŸtirilmemiÅŸse, direk olarak bu derlenmiÅŸ dll kullanÄ±lacaktÄ±r. Bu yÃ¼zden view&#8217;in ilk Ã§alÄ±ÅŸtÄ±rÄ±lmasÄ±ndan sonra bÃ¼yÃ¼k bir performans artÄ±ÅŸÄ± da olacaktÄ±r.</p><p
style="text-align: justify;">Burada dikkat etmemiz gereken diÄŸer bir husus ise bu Ã¼retilmiÅŸ olan dosyada view dosyamÄ±z bir sÄ±nÄ±f haline dÃ¶nÃ¼ÅŸtÃ¼rÃ¼lmÃ¼ÅŸ ve <em>WebViewPage&lt;*.BirModel&gt;</em> gibi bir sÄ±nÄ±ftan tÃ¼retilmiÅŸtir. Ä°ÅŸte <strong>&#8220;strongly typed&#8221;</strong> deÄŸimi buradan geliyor. View dosyamÄ±z, dosyanÄ±n baÅŸÄ±nda model belirteci ile belirttiÄŸimiz modeli <strong>generic parametre</strong> olarak alan bir sÄ±nÄ±ftan tÃ¼retilmekte.</p><p
style="text-align: justify;">Tabi ki bu Ã¼retilen dosyanÄ±n Ã§ok da ayrÄ±ntÄ±sÄ±na inmemize lÃ¼zum yok. Fakat View&#8217;in Ã§alÄ±ÅŸma mantÄ±ÄŸÄ±nÄ± anlama aÃ§Ä±sÄ±ndan bu kÄ±sÄ±m Ã¶nemliydi.</p><h1>ViewBag ve ViewData</h1><p
style="text-align: justify;"><strong>ViewBag</strong> ve <strong>ViewData</strong> aslÄ±nda aynÄ± iÅŸi yapan ve view ile model&#8217;e alternatif olarak controller arasÄ±nda iletiÅŸimi saÄŸlayan iki yÃ¶ntemdir. <em>ViewBag</em>, C#&#8217;Ä±n <strong>dinamik nesne</strong> Ã¶zelliÄŸini kullanan bir nesnedir. <em>ViewData</em> ise indeksli bir <em>Dictionary</em> nesnesidir. Dinamik nesne desteklemeyen eski sÃ¼rÃ¼m .net&#8217;lerde ViewData kullanÄ±lmaktadÄ±r. Yeni versiyonlarda hem ViewBag hem de ViewData kullanÄ±labilir. AÅŸaÄŸÄ±daki kod hem controller&#8217;da hem de view dosyasÄ±nda aynÄ± ÅŸekilde kullanÄ±labilir:</p><pre>
<pre class="brush: csharp">public ActionResult Index()
{
    ViewBag.BirYazi = &quot;Diyezon&quot;;
    ViewData[&quot;BirSayi&quot;] = 5;
    return View();
}</pre></pre><p
style="text-align: justify;">View dosyasÄ± iÃ§inde ise:</p><pre>
<pre class="brush: csharp">&lt;p&gt;YazÄ±: @ViewBag.BirYazi&lt;/p&gt;
&lt;p&gt;SayÄ±: @ViewData[&quot;BirSayi&quot;]&lt;/p&gt;</pre></pre><p
style="text-align: justify;">Normalde ViewBag ve ViewData iÃ§inde Ã§ok fazla kompleks olmayan ve miktarÄ± az verileri barÄ±ndÄ±rmanÄ±z performans aÃ§Ä±sÄ±ndan daha iyi olacaktÄ±r. Bir kaÃ§ baÅŸlÄ±k sonra da gÃ¶rebilceÄŸiniz gibi bu nesneleri aÅŸÄ±rÄ± derecede kullanmak performansÄ± dÃ¼ÅŸÃ¼recektir. Bu nesnler genelde, model&#8217;de deÄŸiÅŸiklik yapamadÄ±ÄŸÄ±nÄ±z ya da yapmak istemediÄŸiniz durumlarda kullanÄ±lÄ±rlar. View iÃ§ine gÃ¶ndereceÄŸimiz veriler iÃ§in ilk Ã¶nce model yapÄ±sÄ±nÄ± dÃ¼ÅŸÃ¼nmeliyiz.</p><h1>Html YardÄ±mcÄ± MetodlarÄ±(Html Helpers)</h1><p
style="text-align: justify;">Ä°lk makalede de bahsettiÄŸimiz gibi MVC, WebForms&#8217;daki gibi tut taÅŸÄ± mantÄ±ÄŸÄ± yerine her bir elemanÄ±n elle girilmesini ister. Ä°lk baÅŸta bu zor gibi gÃ¶rÃ¼nse de projenin ilerleyen aÅŸamalarÄ±nda, tut taÅŸÄ± ve viewstate mantÄ±ÄŸÄ±ndan Ã§ok daha verimli olduÄŸunu gÃ¶receksiniz. Ã–zellikle Ã¼retilen html kodu, WebForms&#8217;daki gibi istemediÄŸiniz bir Ã§ok Ä±vÄ±r zÄ±vÄ±r html kodlarÄ± ile sarÄ±lÄ± olmayacaktÄ±r. Bunun ayrÄ±ntÄ±sÄ±nÄ± ilk makalenin baÅŸlarÄ±nda bahsetmiÅŸtik. FarkÄ±nda iseniz &#8220;Ã¼retilen&#8221; html kodundan bahsettim. Evet her ne kadar MVC her ÅŸeyi bizim belirlememizi istese de bize yardÄ±mcÄ± olacak bir Ã§ok metodu da hizmetimize sunmaktadÄ±r.</p><p
style="text-align: justify;">Html yardÄ±mcÄ± metodlarÄ±, <em>System.Mvc.HtmlHelpers</em> ismindeki statik bir sÄ±nÄ±fta bulunan metodlardan oluÅŸmaktadÄ±r. Bu metodlar ile dinamik olarak oluÅŸturulmasÄ± gereken bir Ã§ok iÅŸi gerÃ§ekleÅŸtirebiliriz. Åžimdi ilk baÅŸta hazÄ±r yardÄ±mcÄ± metodlardan en Ã§ok kullanacaÄŸÄ±mÄ±z bir kaÃ§ tanesini gÃ¶relim ve ardÄ±ndan kendi yardÄ±mcÄ± metodlarÄ±mÄ±zÄ± nasÄ±l oluÅŸturacaÄŸÄ±mÄ±zÄ± gÃ¶relim.</p><h2>Form OluÅŸturma</h2><p
style="text-align: justify;">Form oluÅŸturmak iÃ§in biri Ã§irkin ve uzun diÄŸeri kÄ±sa ve pratik iki yÃ¶ntemimiz var. Uzun yÃ¶ntem:</p><pre>
<pre class="brush: csharp">@{ Html.BeginForm(); }
@{ Html.EndForm(); }</pre></pre><p
style="text-align: justify;">Bu iki kod arasÄ±na yazacaÄŸÄ±nÄ±z her ÅŸey form iÃ§inde olacaktÄ±r. Fakat bunun daha pratik yolu ise:</p><pre>
<pre class="brush: csharp">@using(Html.BeginForm())
{
}</pre></pre><p
style="text-align: justify;">olacaktÄ±r. Bu blok iÃ§ine yazacaÄŸÄ±nÄ±z bÃ¼tÃ¼n kodlar form iÃ§inde bulunacaktÄ±r. <em>BeginForm</em> metodu normalde <em>IDisposable</em> arayÃ¼zÃ¼nÃ¼ tanÄ±mlayan <em>MvcForm</em> tipinde bir sÄ±nÄ±f Ã¼retecektir. <em>IDisposable</em> olduÄŸundan dolayÄ± <em>using</em> terimi ile sardÄ±ÄŸÄ±mÄ±zda, .Net <em>using</em> bloÄŸunun bitiminde bu sÄ±nÄ±fÄ±n <em>Dispose()</em> metodunu Ã§aÄŸÄ±racaktÄ±r. Bu da <em>EndForm</em> metodunu tetikleyecektir.</p><p
style="text-align: justify;">Burada verdiÄŸimiz Ã¶rnekte form onaylandÄ±ÄŸÄ± zaman sonucu bu view&#8217;i Ã§aÄŸÄ±ran action metoduna gÃ¶nderecektir. EÄŸer baÅŸka bir action&#8217;a gÃ¶nderim yapmak istersek:</p><pre>
<pre class="brush: csharp">@using(Html.BeginForm(&quot;BirAction&quot;, &quot;BirController&quot;))
{
}</pre></pre><p
style="text-align: justify;">yazmalÄ±yÄ±z. BeginForm metodunun diÄŸer parametrelerini yardÄ±m dosyasÄ±nda bakabilirsiniz.</p><h2>Form ElemanlarÄ±nÄ± OluÅŸturma</h2><p
style="text-align: justify;">Form elemanlarÄ±nÄ± oluÅŸturmak iÃ§in iki farklÄ± metod grubumuz var. Bu gruplardan birisi zorunlu olarak modeli kullanan diÄŸeri ise model kullanmayan metodlardÄ±r.</p><h3>Model Zorunlu Olmayanlar</h3><p
style="text-align: justify;">Ä°lk baÅŸta model zorunlu olmayan metodlarÄ± gÃ¶relim:</p><pre>
<pre class="brush: csharp">@Html.Label(&quot;FormElemanAdi&quot;)
//&lt;label for=&quot;FormElemanAdi &gt;Form elemanÄ±nÄ±n texti&lt;/label&gt;

@Html.CheckBox(&quot;CheckBoxAdi&quot;, true)
//&lt;input checked=&quot;checked&quot; id=&quot;CheckBoxAdi&quot; name=&quot;CheckBoxAdi&quot; type=&quot;checkbox&quot; value=&quot;true&quot; /&gt;
//&lt;input name=&quot;CheckBoxAdi&quot; type=&quot;hidden&quot; value=&quot;false&quot; /&gt;

@Html.Hidden(&quot;HiddenAdi&quot;, &quot;HiddenDegeri&quot;)
//&lt;input id=&quot;HiddenAdi&quot; name=&quot;HiddenAdi&quot; type=&quot;hidden&quot; value=&quot;val&quot; /&gt;

@Html.RadioButton(&quot;RadioAdi&quot;,&quot;RadioDegeri&quot;, true)
//&lt;input checked=&quot;checked&quot; id=&quot;RadioAdi&quot; name=&quot;RadioAdi&quot; type=&quot;radio&quot; value=&quot;RadioDegeri&quot; /&gt;

@Html.Password(&quot;PasswordAdi&quot;, &quot;PasswordDegeri&quot;)
//&lt;input id=&quot;PasswordAdi&quot; name=&quot;PasswordAdi&quot; type=&quot;password&quot; value=&quot;PasswordDegeri&quot; /&gt;

@Html.TextArea(&quot;TextAreaAdi&quot;, &quot;TextAreaDegeri&quot;)
//&lt;textarea id=&quot;TextAreaAdi&quot; name=&quot;TextAreaAdi&quot;&gt;TextAreaDegeri&lt;/textarea&gt;

@Html.TextBox(&quot;TextBoxAdi&quot;, &quot;TextBoxDegeri&quot;)
//&lt;input id=&quot;TextBoxAdi&quot; name=&quot;TextBoxAdi&quot; type=&quot;text&quot; value=&quot;TextBoxDegeri&quot; /&gt;</pre></pre><p
style="text-align: justify;">(Buradaki aÃ§Ä±klama satÄ±rlarÄ± tabiki Razor iÃ§in uygun bir aÃ§Ä±klama satÄ±rÄ± deÄŸil. Fakat sitede kullandÄ±ÄŸÄ±m syntax renklendirici iÃ§in bÃ¶yle yazmak zorunda kaldÄ±m.)</p><p
style="text-align: justify;">FarkÄ±nda iseniz <em>CheckBox</em> ile iki adet kod Ã¼retildi. Normalde browser checkbox seÃ§ili olmadÄ±ÄŸÄ±nda sunucuya bu deÄŸeri yollamaz. Bu yÃ¼zden MVC bu durumu dÃ¼ÅŸÃ¼nerek buraya deÄŸeri false olan bir hidden form elemanÄ± ekleyerek checkbox seÃ§ilmediÄŸinde deÄŸer olarak false yollanmasÄ± saÄŸlanmaktadÄ±r.</p><p
style="text-align: justify;">FarkÄ±nda iseniz ilk deÄŸer olarak eleman adÄ±nÄ± ve ikinci deÄŸer olarak da elemanÄ±n deÄŸerini yazÄ±yoruz. EÄŸer elemanÄ±n deÄŸerini girmezsek ve sadece adÄ±nÄ± verirsek:</p><pre>
<pre class="brush: csharp">@Html.TextBox(&quot;TextBoxAdi&quot;)</pre></pre><p
style="text-align: justify;">bu durumda deÄŸer olarak MVC otomatik olarak bir kaÃ§ yere bakacaktÄ±r:</p><pre>
<pre class="brush: csharp">ViewBag.TextBoxAdi
ViewData[&quot;TextBoxAdi&quot;]
Model.TextBoxAdi</pre></pre><p
style="text-align: justify;">Tabi burada bakÄ±lan deÄŸerin tipi ile Html yardÄ±mcÄ± metodunun deÄŸer tipi aynÄ± olacaktÄ±r. Yani <em>CheckBox</em> metodu iÃ§in <em>boolean</em> tipinde bir deÄŸer aranacaktÄ±r.</p><p
style="text-align: justify;">Åžimdi daha ilginÃ§ bir ÅŸey yapalÄ±m ve isim olarak ÅŸÃ¶yle bir ÅŸey girelim:</p><pre>
<pre class="brush: csharp">@Html.CheckBox(&quot;Veriler.Secenekler.Secenek&quot;)</pre></pre><p>Bu durumda bakÄ±lacak kÄ±sÄ±mlar daha da uzayacaktÄ±r:</p><pre>
<pre class="brush: csharp">ViewBag.Veriler.Secenekler.Secenek
ViewBag.Veriler[&quot;Secenekler&quot;].Secenek
ViewBag.Veriler[&quot;Secenekler.Secenek&quot;]
ViewBag.Veriler[&quot;Secenekler&quot;][&quot;Secenek&quot;]
.....</pre></pre><p
style="text-align: justify;">Tabi bu liste uzunca bir liste olacaktÄ±r. GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi girdiÄŸiniz isimler MVC iÃ§in Ã¶nemli bir deÄŸer arzediyor. Bu yÃ¶ntemde her ne kadar performans dÃ¼ÅŸÃ¼ÅŸÃ¼ olacak gibi gÃ¶rÃ¼nse de ViewBag ve ViewData iÃ§inde sadece <strong>bir kaÃ§tane deÄŸer</strong> olacaÄŸÄ± iÃ§in performans dÃ¼ÅŸÃ¼ÅŸÃ¼ de beklenmez. Tabi Ã¶nceden de bahsettiÄŸimiz gibi ViewBag ve ViewData&#8217;da<strong> Ã§ok az miktarda</strong> veri bulundurmalÄ±sÄ±nÄ±z.</p><h3>Model Zorunlu Olanlar</h3><p
style="text-align: justify;">Html yardÄ±mcÄ± metodlarÄ±nda adÄ±Â  &#8220;<strong>For</strong>&#8221; ile biten metodlar, modeller iÃ§in Ã¶zel olarak tasarlanmÄ±ÅŸtÄ±r. Hem performans hem de kolay kullanÄ±m aÃ§Ä±sÄ±ndan mÃ¼mkÃ¼n olduÄŸunca bu tarz metodlarÄ± kullanmanÄ±zÄ± tavsiye ediyorum.</p><p
style="text-align: justify;">Bir Ã¶nceki baÅŸlÄ±kta verdiÄŸimiz metodlarÄ±n tek tek buradaki karÅŸÄ±lÄ±klarÄ±nÄ± vermek yerine, basit bir Ã¶rnek yapalÄ±m. Makalenin baÅŸÄ±nda yaptÄ±ÄŸÄ±mÄ±z Ã¶rnekte bir model oluÅŸturmuÅŸtuk. Bu modeli aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim:</p><pre>
<pre class="brush: csharp">Â Â Â  public class BirModel
Â Â Â  {
Â Â Â Â Â Â Â  [DisplayName(&quot;KullanÄ±cÄ± AdÄ±&quot;)]
Â Â Â Â Â Â Â  public string KullaniciAdi { get; set; }

Â Â Â Â Â Â Â  [DisplayName(&quot;Åžifre&quot;)]
Â Â Â Â Â Â Â  [DataType(DataType.Password)]
Â Â Â Â Â Â Â  public string Sifre { get; set; }

Â Â Â Â Â Â Â  [DisplayName(&quot;Beni HatÄ±rla&quot;)]
Â Â Â Â Â Â Â  public bool BeniHatirla { get; set; }

        public int BirListeDegeri { get; set; }
Â Â Â Â Â Â Â  public Dictionary&lt;int,string&gt; BirListe { get; set; }
Â Â Â  }</pre></pre><p
style="text-align: justify;">Buradaki kullanÄ±lan <em>DisplayName</em>, <em>DataType</em> gibi Ã¶znitelikleri ÅŸimdilik gÃ¶rmezden gelin. Ã‡Ã¼nkÃ¼ bu kÄ±sÄ±m gelecek makalenin konusu. Ama ne iÅŸe yaradÄ±klarÄ±nÄ± View dosyasÄ±nÄ± gÃ¶rdÃ¼kten sonra tahmin edersiniz herhalde. Åžimdi View dosyamÄ±zÄ± aÃ§alÄ±m ve aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim:</p><pre>
<pre class="brush: csharp">@model MvcArticle3_1.Models.BirModel
@{
Â Â Â  ViewBag.Title = &quot;Ana sayfa&quot;;
}

@using (Html.BeginForm())
{
Â Â Â  &lt;table&gt;
Â Â Â Â Â Â Â  &lt;tr&gt;
Â Â Â Â Â Â Â Â Â Â Â  &lt;th&gt;@Html.LabelFor(m =&gt; m.KullaniciAdi)&lt;/th&gt;
Â Â Â Â Â Â Â Â Â Â Â  &lt;td&gt;@Html.EditorFor(m =&gt; m.KullaniciAdi)&lt;/td&gt;
Â Â Â Â Â Â Â  &lt;/tr&gt;
Â Â Â Â Â Â Â  &lt;tr&gt;
Â Â Â Â Â Â Â Â Â Â Â  &lt;th&gt;@Html.LabelFor(m =&gt; m.Sifre)&lt;/th&gt;
Â Â Â Â Â Â Â Â Â Â Â  &lt;td&gt;@Html.EditorFor(m =&gt; m.Sifre)&lt;/td&gt;
Â Â Â Â Â Â Â  &lt;/tr&gt;
Â Â Â Â Â Â Â  &lt;tr&gt;
Â Â Â Â Â Â Â Â Â Â Â  &lt;th&gt;@Html.LabelFor(m =&gt; m.BeniHatirla)&lt;/th&gt;
Â Â Â Â Â Â Â Â Â Â Â  &lt;td&gt;@Html.EditorFor(m =&gt; m.BeniHatirla)&lt;/td&gt;
Â Â Â Â Â Â Â  &lt;/tr&gt;
Â Â Â  &lt;/table&gt;
}</pre></pre><p
style="text-align: justify;">Ã–nceki Ã¶rnekte dediÄŸim gibi model tanÄ±mlamasÄ±ndaki namespace sizde farklÄ± olabilir, bunu deÄŸiÅŸtirebilirsiniz.</p><p
style="text-align: justify;">Åžimdi de son olarak <em>Index</em> action metodumuzu aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim:</p><pre>
<pre class="brush: csharp">Â Â Â Â Â Â Â  public ActionResult Index()
Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â  return View();
Â Â Â Â Â Â Â  }</pre></pre><p
style="text-align: justify;">Derleyip Ã§alÄ±ÅŸtÄ±rdÄ±ÄŸÄ±mÄ±zda hazÄ±rladÄ±ÄŸÄ±mÄ±z modele uygun bir form ile karÅŸÄ±laÅŸacaÄŸÄ±z. Åžimdilik model&#8217;deki Ã¶znitelik tanÄ±mlamalarÄ± ve bu form gÃ¶nderildikten sonra iÅŸlenecek kÄ±smÄ± daha sonraki makaleye havale ederek burada sadece View dosyasÄ±ndaki eklediÄŸimiz metodlara gÃ¶z atalÄ±m.</p><p
style="text-align: justify;">FarkÄ±ndaysanÄ±z sadece <em>EditorFor</em> metodunu kullanarak Ã¼Ã§ farklÄ± form elemanÄ± oluÅŸturduk. <em>EditorFor</em> metodu, belirtilen modeldeki Ã¶zelliÄŸin tipini tespit ederek uygun bir form elemanÄ±nÄ± sayfaya render etti.</p><p
style="text-align: justify;">Parametre olarak girilen <strong>delegate</strong> ile model iÃ§inden herhangi bir Ã¶zelliÄŸi seÃ§ebiliyoruz. Gerisini metod hallediyor. Tabi ki, bir Ã¶nceki baÅŸlÄ±kta verdiÄŸimiz CheckBox, TextBox gibi metodlarÄ±n <em>CheckBoxFor</em>, <em>TextBoxFor</em> metod karÅŸÄ±lÄ±klarÄ± da mevcut. BunlarÄ±n <em>EditorFor</em>&#8216;dan tek farkÄ±, form elemanÄ±nÄ±n tipinin seÃ§imini size bÄ±rakmasÄ±dÄ±r. Ama model Ã¼zerinde bu seÃ§imi yapmak, projenin ilerleyen aÅŸamasÄ±nda da fark edeceksiniz, <strong>daha az</strong> kullanÄ±ÅŸlÄ±dÄ±r. Ã‡Ã¼nkÃ¼ belli bir sÃ¼re sonra, bir veri tipinde deÄŸiÅŸiklik yaptÄ±ÄŸÄ±nÄ±zda tÃ¼m view&#8217;leri araÅŸtÄ±rÄ±p bu tipe ait metodu da deÄŸiÅŸtirmeniz gerekebilir. Bu yÃ¼zden tÃ¼m etiket ve tip tanÄ±mlamalarÄ±nÄ± model altÄ±nda merkezi bir yerde toplamÄ±ÅŸ olduk. Bu konunun ayrÄ±ntÄ±sÄ±nÄ± kÄ±smetse gelecek makalede gÃ¶receÄŸiz.</p><p
style="text-align: justify;">AynÄ± ÅŸekilde <em>EditorFor</em> yerine <em>DisplayFor</em> metodunu kullanarak, form elemanÄ± yerine sadece <strong>okunabilir</strong> formatta, modellin deÄŸerini kullanÄ±cÄ±ya gÃ¶sterebiliriz.</p><p
style="text-align: justify;">Bu metodlarÄ±n haricinde bir de <em>EditorForModel</em> gibi &#8220;<strong>ForModel</strong>&#8221; ile biten metodlar da vardÄ±r. Bu metodlar belli bir <strong>template</strong>, ÅŸema ile model&#8217;e ait tÃ¼m Ã¶zellikleri ekrana basacaktÄ±r. Ä°lerleyen makalelerde bu metodlar iÃ§in template hazÄ±rlamayÄ± da gÃ¶receÄŸiz, fakat ÅŸimdilik bu konuyu es geÃ§elim.</p><p
style="text-align: justify;"><strong>Devam etmek iÃ§in diÄŸer sayfaya geÃ§iniz.</strong></p> ]]></content:encoded> <wfw:commentRss>http://www.diyezon.com/asp-net-mvc-view/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>ASP.NET MVC &#8211; Proje, YÃ¶nlendirme</title><link>http://www.diyezon.com/asp-net-mvc-proje-yonlendirme/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=asp-net-mvc-proje-yonlendirme</link> <comments>http://www.diyezon.com/asp-net-mvc-proje-yonlendirme/#comments</comments> <pubDate>Sun, 14 Aug 2011 12:29:05 +0000</pubDate> <dc:creator>Fatih Tolga Ata</dc:creator> <category><![CDATA[ASP.NET]]></category> <category><![CDATA[MVC]]></category> <category><![CDATA[asp.net]]></category> <category><![CDATA[mvc]]></category> <category><![CDATA[routing]]></category> <category><![CDATA[yÃ¶nlendirme]]></category><guid
isPermaLink="false">http://www.diyezon.com/?p=366</guid> <description><![CDATA[GeÃ§en haftaki yazÄ±mÄ±zda ASP.NET MVC&#8217;ye giriÅŸ yapmÄ±ÅŸtÄ±k. ASP.NET MVC&#8217;nin klasik Web Form mantÄ±ÄŸÄ±na gÃ¶re avantajlarÄ±ndan ve MVC&#8217;nin Ã§alÄ±ÅŸma mantÄ±ÄŸÄ±ndan bahsetmeye Ã§alÄ±ÅŸtÄ±k. Yine ASP.NET MVC 3 ile birlikte gelen Razor gÃ¶rÃ¼nÃ¼m motorunu da baÅŸlangÄ±Ã§ dÃ¼zeyinde bahis konusu yapmÄ±ÅŸtÄ±k. ArdÄ±ndan MVC Ã§alÄ±ÅŸma mantÄ±ÄŸÄ±nÄ±n kafamÄ±zda somut bir ÅŸekilde yer etmesi iÃ§in bir Ã¶rnek yapmÄ±ÅŸtÄ±k. EÄŸer ASP.NET MVC&#8217;ye yabancÄ± [...]]]></description> <content:encoded><![CDATA[<p
style="text-align: justify;">GeÃ§en haftaki <a
title="ASP.NET MVC ve Razorâ€™a GiriÅŸ" href="http://www.diyezon.com/2011/08/07/asp-net-mvc-ve-razora-giris/" target="_blank">yazÄ±mÄ±zda</a> ASP.NET MVC&#8217;ye giriÅŸ yapmÄ±ÅŸtÄ±k. ASP.NET MVC&#8217;nin klasik Web Form mantÄ±ÄŸÄ±na gÃ¶re avantajlarÄ±ndan ve MVC&#8217;nin Ã§alÄ±ÅŸma mantÄ±ÄŸÄ±ndan bahsetmeye Ã§alÄ±ÅŸtÄ±k. Yine ASP.NET MVC 3 ile birlikte gelen Razor gÃ¶rÃ¼nÃ¼m motorunu da baÅŸlangÄ±Ã§ dÃ¼zeyinde bahis konusu yapmÄ±ÅŸtÄ±k. ArdÄ±ndan MVC Ã§alÄ±ÅŸma mantÄ±ÄŸÄ±nÄ±n kafamÄ±zda somut bir ÅŸekilde yer etmesi iÃ§in bir Ã¶rnek yapmÄ±ÅŸtÄ±k. EÄŸer ASP.NET MVC&#8217;ye yabancÄ± iseniz ilk baÅŸta bu <a
title="ASP.NET MVC ve Razorâ€™a GiriÅŸ" href="http://www.diyezon.com/2011/08/07/asp-net-mvc-ve-razora-giris/" target="_blank">ilk makaleden</a> baÅŸlamanÄ±zÄ± tavsiye ederim.</p><p
style="text-align: justify;">Bu yazÄ±da, konuya kaldÄ±ÄŸÄ±mÄ±z yerden devam edeceÄŸiz ve ASP.NET MVC projesinin yapÄ±sÄ±nÄ± inceleyeceÄŸiz. ArdÄ±ndan ASP.NET MVC&#8217;de Ã§okca kullanÄ±lan yÃ¶nelendirme mantÄ±ÄŸÄ±ndan bahsedeceÄŸiz. Ki bu konu ASP.NET MVC &#8216;de ciddi bir proje geliÅŸtirebilmemiz iÃ§in temel konularÄ± kapsÄ±yor.</p><p><span
id="more-366"></span></p><h1>ASP.NET MVC Projesi</h1><p
style="text-align: justify;">VWD ya da VS&#8217;de yeni bir MVC projesi oluÅŸturmaya kalktÄ±ÄŸÄ±nÄ±zda IDE size Ã¼Ã§ ÅŸablon(template) seÃ§eneÄŸi sunacak. Bunlardan birincisi <em>Empty</em> ÅŸablonu, Ã¶nceki makalede kullandÄ±ÄŸÄ±mÄ±z bir ÅŸablondu. En basit haliyle bir ASP.NET MVC projesinin barÄ±ndÄ±racaÄŸÄ± dosyalar bu ÅŸablonda bulunmaktadÄ±r. DiÄŸer ÅŸablonlar olan <em>Internet</em> ve <em>Intranet</em> ÅŸablonlarÄ± ise size daha geniÅŸ baÅŸlangÄ±Ã§ noktalarÄ± sunmaktadÄ±r. Internet ÅŸablonu ile varsayÄ±lan bir controller ve bir view dosyasÄ± projeye dahil edilcektir. Intranet ÅŸablonun Internet ÅŸablonundan tek farkÄ± ekstradan kullanÄ±cÄ± iÅŸlemlerinin olmasÄ±dÄ±r. Biz genelde Empty ÅŸablonunu kullanmaktayÄ±z. Fakat kÃ¼Ã§Ã¼k bir takÄ±m iÅŸler iÃ§in hazÄ±r bu ÅŸablonlarÄ± kullanabilirsiniz. Mesela bu makalede bahsedilecek olan yÃ¶nlendirmeler Ã¼zerinde denemeler yaparken hazÄ±r Internet ÅŸablonunu kullanabilirsiniz. Tabi ki bu ÅŸablonlara ek olarak kendiniz de bir proje ÅŸablonu oluÅŸturabilirsiniz. Fakat bu konu makalenin sÄ±nÄ±rlarÄ± dÄ±ÅŸÄ±nda&#8230;</p><p>Empty ÅŸablonu oluÅŸturduÄŸunuz bir projenin klasÃ¶r yapÄ±sÄ± aÅŸaÄŸÄ±daki gibi olmaktadÄ±r:</p><ul><li
style="text-align: justify;"><strong>App_Data:</strong> Bu MVC&#8217;ye Ã¶zel bir klasÃ¶r deÄŸildir. VeritabanÄ± dosyalarÄ±nÄ±n tutulduÄŸu klasÃ¶rdÃ¼r. IIS bu dosyaya eriÅŸimi kÄ±sÄ±tlayacaktÄ±r. KullandÄ±ÄŸÄ±nÄ±z host bu klasÃ¶r altÄ±nda veritabanÄ± bulundurmanÄ±za izin veriyorsa kullanabilirsiniz.</li><li
style="text-align: justify;"><strong>bin:</strong> DerlenmiÅŸ proje dosyalarÄ±dÄ±r. IIS bu klasÃ¶re eriÅŸim vermediÄŸi gibi VS ya da VWD de bu klasÃ¶rÃ¼ Solution Explorer&#8217;da gizler. Projeyi tamamlayÄ±p hosta taÅŸÄ±yÄ±ncaya kadar iÅŸiniz olmaz bu klasÃ¶rle.</li><li
style="text-align: justify;"><strong>Content:</strong> Bu klasÃ¶r ismi kabullenmedir ve zorunlu deÄŸildir. CSS ve resim gibi statik dosyalarÄ±nÄ±zÄ± bu klasÃ¶re koyabilirsiniz. Fakat zorunlu olmadÄ±ÄŸÄ± iÃ§in istediÄŸiniz klasÃ¶rÃ¼ de kullanabilirsiniz.</li><li
style="text-align: justify;"><strong>Controllers:</strong> Controller sÄ±nÄ±flarÄ±nÄ± koyduÄŸumuz klasÃ¶rdÃ¼r. Bu klasÃ¶rÃ¼n ismi de zorunlu deÄŸildir. Ã‡Ã¼nkÃ¼ sonuÃ§ta bunlar derlenip aynÄ± assembly iÃ§ine girecekler.</li><li
style="text-align: justify;"><strong>Models:</strong> Model sÄ±nÄ±flarÄ±nÄ± yerleÅŸtirdiÄŸimiz klasÃ¶rdÃ¼r. Bu klasÃ¶rÃ¼n ismi de kabullenmedir ve zorunlu deÄŸildir. Ã‡Ã¼nkÃ¼ sonuÃ§ta bu sÄ±nÄ±flar derlenip bir assembly oluÅŸtururlar ve bin klasÃ¶rÃ¼ne yerleÅŸtirilirler.</li><li
style="text-align: justify;"><strong>Scripts:</strong> Bu da Content klasÃ¶rÃ¼ gibi zorunlu deÄŸildir. Javascript dosyalarÄ±nÄ± bu klasÃ¶rde tutabilirsiniz.</li><li
style="text-align: justify;"><strong>Views:</strong> View ve partial view dosyalarÄ± bu klasÃ¶rde tutulur. AyrÄ±ca bu klasÃ¶rde bulunan <em>Shared</em> klasÃ¶rÃ¼ <em>layout</em> ve tÃ¼m controller&#8217;lar tarafÄ±ndan kullanÄ±labilecek ortak view dosyalarÄ±nÄ± tutarlar. Bu klasÃ¶r IIS tarafÄ±ndan servis edilmez yani eriÅŸimi kÄ±sÄ±tlanmÄ±ÅŸtÄ±r. Bu klasÃ¶rÃ¼n ana dizininde bir web.config dosyasÄ± mevcuttur. Bu web.config, uygulamanÄ±n web.config dosyasÄ±ndan ayrÄ±dÄ±r ve bu klasÃ¶rÃ¼n IIS tarafÄ±ndan servis edilmesini engeller. Bu klasÃ¶rÃ¼n ismi kabullenme <strong>deÄŸildir</strong>. Fakat MVC&#8217;nin yapÄ±sÄ±nÄ± Ã¶zelleÅŸtirerek view dosyalarÄ±nÄ±n baÅŸka klasÃ¶rde aranmasÄ±nÄ± saÄŸlayabilirsiniz. Tabi bu makalemizin sÄ±nÄ±rlarÄ± dÄ±ÅŸÄ±nda bir konu&#8230;</li></ul><p
style="text-align: justify;">Bu klasÃ¶rler dÄ±ÅŸÄ±nda ana dizinde uygulamanÄ±n bir adet web.config dosyasÄ± ve bu makalede kÄ±smen bahsedceÄŸimiz uygulamanÄ±n sÄ±nÄ±fÄ±nÄ± iÃ§eren <em>Global.asax</em> dosyasÄ± mevcuttur. Bunlar dÄ±ÅŸÄ±nda ilerideki makalelerde bahsetmek istediÄŸim bir konu olan alanlarla ilgili olan <em>Areas</em> klasÃ¶rÃ¼ mevcut olacaktÄ±r. Yeni bir alan oluÅŸturduÄŸunuzda VWD bu klasÃ¶rÃ¼ otomatik olarak projeye dahil edecektir.</p><p
style="text-align: justify;">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi Ã§oÄŸu klasÃ¶r ismi zorunlu deÄŸildir ve her nasÄ±l istiyorsanÄ±z klasÃ¶r yapÄ±sÄ±nÄ± o ÅŸekilde ÅŸekillendirebilirsiniz. Fakat Views klasÃ¶rÃ¼ diÄŸerlerinden farklÄ± bir yapÄ±ya sahiptir.</p><p
style="text-align: justify;">Ä°simlendirme ile ayarlama diyebileceÄŸimiz bu yapÄ±, Ruby on Rails&#8217;in bu kadar tutmasÄ±nÄ±n nedenlerinden biridir aslÄ±nda. Bu yapÄ± sayesinde Controller sÄ±nÄ±flarÄ± ve View dosyalarÄ± arasÄ±nda ekstra bir iliÅŸkilendirme yapmak zorunda kalmÄ±yorsunuz. Ä°ÅŸin gÃ¼zel tarafÄ±, ilgili Controller sÄ±nÄ±fÄ±na ait bir View eklemek istiyorsanÄ±z, sadece bu Controller sÄ±nÄ±fÄ± ile <em>aynÄ± ismi</em> taÅŸÄ±yan bir klasÃ¶r iÃ§ine View dosyanÄ±zÄ± yerleÅŸtirmeniz yeterlidir. Mesela AnaSayfa isimli bir Controller sÄ±nÄ±fÄ±nÄ±n Index adlÄ± bir action metodu varsa bu action metoda ait View dosyasÄ±, /Views/AnaSayfa/Index.cshtml dosyasÄ± olacaktÄ±r. Bu varsayÄ±lan isimlendirme yapÄ±sÄ±nÄ± isterseniz yeni bir Controller Factory tanÄ±mlayarak deÄŸiÅŸtirebilirsiniz. Bu makalemizin konusu deÄŸil, ama illaki incelemek isterseniz <em>DefaultControllerFactory</em> sÄ±nÄ±fÄ±nÄ± ve <em>IControllerFactory</em> arayÃ¼zÃ¼nÃ¼ inceleyebilirsiniz.</p><p
style="text-align: justify;">Bu yapÄ± sayesinde gÃ¶stermek istediÄŸimiz bir View dosyasÄ±nÄ± action method&#8217;dan dÃ¶nÃ¼ÅŸ yapmamÄ±z kafidir. Mesela:</p><pre style="text-align: justify;">
<pre class="brush: csharp">
public ActionResult Index()
{
    return View();
}
</pre></pre><p
style="text-align: justify;">ile Index metoduna ait Index.cshtml dosyasÄ±nÄ± dÃ¶nderirsiniz. EÄŸer baÅŸka bir view dosyasÄ±nÄ± sonuÃ§ vermek isterseniz:</p><pre style="text-align: justify;">
<pre class="brush: csharp">
public ActionResult Index()
{
    return View(&quot;BaskaBirView&quot;); //AynÄ± controller iÃ§indeki BaskaBirView.cshtml dosyasÄ±
}
</pre></pre><p
style="text-align: justify;">yazmanÄ±z kafi gelecektir. Tabi bu son Ã¶rnekte eÄŸer aynÄ± controller klasÃ¶rÃ¼nde bu dosya bulunamazsa Shared klasÃ¶rÃ¼ne baÅŸvurulacaktÄ±r. AyrÄ±ca &#8220;.cshtml&#8221; uzantÄ±sÄ±nÄ± girmediÄŸimize dikkat edin. Ä°lerideki makalelerde action method&#8217;lardan bahsetmek istiyorum. Ä°leride bu konuya daha detaylÄ± bakabiliriz. Åžimdilik bu kadarÄ± yeterli.</p><h1 style="text-align: justify;">YÃ¶nlendirme (Routing)</h1><p
style="text-align: justify;">Web Form ve PHP benzeri yaklaÅŸÄ±mlarda varsayÄ±lan olarak bir url bir dosyaya iÅŸaret eder. ASP.NET MVC ise varsayÄ±lan olarak yÃ¶nlendirme kullanmaktadÄ±r. Yani:</p><pre style="text-align: justify;">http://www.diyezon.com/index.php?p=365&amp;d=07&amp;m=08&amp;y=2011</pre><p
style="text-align: justify;">url&#8217;si yÃ¶nlendirme kullanÄ±lmadÄ±ÄŸÄ± vakit, sunucu index.php dosyasÄ±na eriÅŸmeyi deneyecektir. Fakat url yÃ¶nlendirmesi kullandÄ±ÄŸÄ±nÄ±zda bu url:</p><pre style="text-align: justify;">http://www.diyezon.com/2011/08/07/asp-net-mvc-ve-razora-giris/</pre><p
style="text-align: justify;">gibi bir hal alacaktÄ±r. BÃ¶ylelikle url&#8217;den dosya bilgisine eriÅŸilemez ve seo&#8217;ya ve ziyaretÃ§ilerinize daha uygun url&#8217;ler Ã¼retmiÅŸ olursunuz.</p><p
style="text-align: justify;">MVC kÃ¼tÃ¼phanesi, yÃ¶nlendirmeye o kadar hakimdir ki, yÃ¶nlendirmede yaptÄ±ÄŸÄ±nÄ±z ufak deÄŸiÅŸikliler otomatik olarak tÃ¼m sisteme uygulanÄ±r. BÃ¶ylelikle url ÅŸablonunu deÄŸiÅŸtirseniz bile tÃ¼m sitede tek tek bul deÄŸiÅŸtir yapmak zorunda kalmazsÄ±nÄ±z. Ãœstelik url ÅŸablonu Ã§ok rahat ve zahmetsiz bir ÅŸekilde yapÄ±landÄ±rÄ±labilir.</p><p
style="text-align: justify;">MVC&#8217;de url yÃ¶nlendirmenin iki temel iÅŸlevi vardÄ±r. Bu yÃ¼zden url yÃ¶nlendirmeyi iki kÄ±sÄ±mda inceleyeceÄŸiz. Ä°lk kÄ±sÄ±mda url ÅŸablonlarÄ± oluÅŸtururken, ikinci kÄ±sÄ±mda bunlarÄ±n site genelinde nasÄ±l kullanÄ±ldÄ±ÄŸÄ±nÄ± gÃ¶receÄŸiz.</p><h2 style="text-align: justify;">Gelen URL Ä°stekleri</h2><p
style="text-align: justify;">Gelen url istekleri, ilgili controller ve action methoda iletilirler. Bu yÃ¶nlendirme iÅŸlemi <em>Global.asax</em> dosyasÄ±nda uygulamanÄ±n baÅŸlangÄ±cÄ±nda oluÅŸturulmaktadÄ±r. Global.asax ile kastettiÄŸimiz tabiki code-behind dosyasÄ± olan <em>Global.asax.cs</em> dosyasÄ±dÄ±r. YÃ¶nelndirme iÅŸlemi Global.asax iÃ§in ÅŸu ÅŸekilde tanÄ±mlanmÄ±ÅŸtÄ±r:</p><pre style="text-align: justify;">
<pre class="brush: csharp">
Â Â Â Â Â Â Â  protected void Application_Start()
Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â  ......
Â Â Â Â Â Â Â Â Â Â Â  RegisterRoutes(RouteTable.Routes);
            ......
Â Â Â Â Â Â Â  }
Â Â Â Â Â Â Â  public static void RegisterRoutes(RouteCollection routes)
Â Â Â Â Â Â Â  {
            //Route tanÄ±mlamalarÄ± burada bulunacak.
 Â Â Â Â Â Â  }
</pre></pre><p
style="text-align: justify;">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi web uygulamasÄ± baÅŸlar baÅŸlamaz route yani yÃ¶nelendirme kayÄ±tlarÄ±mÄ±zÄ± gerÃ§ekleÅŸtiriyoruz.</p><p
style="text-align: justify;">Gelen url isteklerinin hangi controller ve action method&#8217;a ait olduÄŸunu belirlemek iÃ§in <em>url ÅŸablonlarÄ±(url pattern)</em> oluÅŸturmamÄ±z gerekiyor. Bunun iÃ§in tek yapmamÄ±z gereken <em>RouteTable</em> sÄ±nÄ±fÄ±nÄ±n <em>Routes</em> kolleksiyonuna yeni bir url ÅŸablonu tanÄ±tmak olacaktÄ±r. Bunu da url ÅŸablonu oluÅŸturma yÃ¶ntemlerinden en pratiÄŸi olan <em>MapRoute</em> metodu ile gerÃ§ekleÅŸtiriyoruz.</p><h3 style="text-align: justify;">URL ÅžablonlarÄ±</h3><p
style="text-align: justify;">YÃ¶nlendirme sistemi bir Ã§ok yÃ¶nlendirmeden oluÅŸan Routes kolleksiyonu ile Ã§alÄ±ÅŸÄ±r. Bu kolleksiyonda tanÄ±mlÄ± olan yÃ¶nelndirmeler, hangi controller ve action method&#8217;un Ã§alÄ±ÅŸtÄ±rÄ±lacaÄŸÄ±nÄ± belirler. Tek tek url&#8217;lerin nereye yÃ¶nlendirileceÄŸini belirtmek yerine <em>url ÅŸablonlarÄ±ndan(url pattern)</em> faydalanÄ±yoruz. Mesela aÅŸaÄŸÄ±daki url&#8217;ye bakalÄ±m:</p><pre style="text-align: justify;"><span style="color: #808080;">http://www.diyezon.com<strong><span style="color: #ff0000;">/</span></strong></span><strong>Home<span style="color: #ff0000;">/</span>Index</strong></pre><p
style="text-align: justify;">Url&#8217;deki ilk kÄ±sÄ±m yani domain kÄ±smÄ± bizi ilgilendirmiyor. Bu yÃ¼zden o kÄ±smÄ± gri ile belirttim. SonrasÄ±nda ise &#8220;/&#8221; slash karakteri ile ayrÄ±lmÄ±ÅŸ olan iki segment(bÃ¶lÃ¼m) gÃ¶rÃ¼yoruz. Birinci segment ile controller&#8217;Ä± ifade ediyoruz, ikinci segment ile Ã§alÄ±ÅŸtÄ±rÄ±lacak olan action method&#8217;u ifade ediyoruz. Tabi biz bunu farkediyoruz fakat sisteme bunu nasÄ±l tanÄ±tacaÄŸÄ±z? Bu Ã¶rnek iÃ§in ÅŸÃ¶yle bir url ÅŸablonu oluÅŸturmamÄ±z kafi gelecektir:</p><pre style="text-align: justify;"><strong>{controller}<span style="color: #ff0000;">/</span>{action}</strong></pre><p
style="text-align: justify;">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi iki adet segment tanÄ±mladÄ±k ve birincisine sÃ¼slÃ¼ parantezler ile controller deÄŸiÅŸkenini, ikinci segment ile de action deÄŸiÅŸkenini belirttik. Bu deÄŸiÅŸkenler(controller ve action) MVC yÃ¶nlendirmede Ã¶zel bir deÄŸere sahiptir. Yani uydurma deÄŸillerdir. Daha sonra gÃ¶receÄŸimiz gibi url pattern iÃ§inde kendi deÄŸiÅŸkenlerimizi de tanÄ±mlayabileceÄŸiz. Fakat isim olarak bu ikisini veremeyiz.</p><p
style="text-align: justify;">GerÃ§ekte yÃ¶nlendirme sistemi, bu ÅŸablonda bulunan deÄŸiÅŸkenleri sadece bir string olarak gÃ¶rÃ¼r. Yani controller deÄŸiÅŸkenini gerÃ§ekte bir MVC controller nesnesi olduÄŸunu bilmez. Zaten yÃ¶nlendirme sistemi MVC kÃ¼tÃ¼phanesine deÄŸil .NET&#8217;e baÄŸlÄ± genel bir sistemdir. Fakat bu aÅŸamadan sonra, yani url&#8217;miz bir pattern kullanarak ayrÄ±ÅŸtÄ±rÄ±ldÄ±ktan sonra, MVC controller ve action deÄŸiÅŸkenlerini alÄ±r ve iÅŸleme koyar.</p><p
style="text-align: justify;">Normalde url ÅŸablonlarÄ± ile istediÄŸiniz kadar segment tanÄ±mlayabilirsiniz. Fakat bu Ã¶rneÄŸimizde sÄ±nÄ±rlÄ± sayÄ±da segment almaktayÄ±z. Sadece bu ÅŸablon ile tanÄ±mlÄ± bir yÃ¶nlendirme sisteminde aÅŸaÄŸÄ±daki url&#8217;lerin aldÄ±klarÄ± sonuÃ§lara bakalÄ±m:</p><pre style="text-align: justify;">http://www.diyezon.com/Home/IndexÂ Â        =&gt; controller = Home,Â  action = Index
http://www.diyezon.com/Index/Home         =&gt; controller = Index, action = Home
http://www.diyezon.com/Home               =&gt; Segment sayÄ±sÄ± az, eÅŸleÅŸme saÄŸlanamaz
http://www.diyezon.com/Home/Index/Module  =&gt; Segment sayÄ±sÄ± fazla, eÅŸleÅŸme saÄŸlanamaz</pre><p
style="text-align: justify;">Son iki Ã¶rnekte eÅŸleÅŸme saÄŸlanamadÄ±ÄŸÄ±ndan, sadece bir url ÅŸablonumuz olduÄŸundan, kullanÄ±cÄ±ya hata verilecektir. Ã–nceden de dediÄŸim gibi yÃ¶nlendirme sistemi deÄŸiÅŸkenlerin iÃ§eriÄŸi ve varlÄ±ÄŸÄ± ile ilgilenmez. Yani ikinci Ã¶rnekte olduÄŸu gibi Index isimli bir controller olmasa dahi bu yÃ¶nlendirmeyi gerÃ§ekleÅŸtirir. Bu yÃ¼zden <strong>eÄŸer segment sayÄ±sÄ± tutuyorsa</strong>, url ne olursa olsun yÃ¶nlendirmede <em>eÅŸleÅŸme</em> saÄŸlanmÄ±ÅŸ demektir.</p><p
style="text-align: justify;">Bu url ÅŸablonunu Global.asax dosyasÄ±nda aÅŸaÄŸÄ±daki gibi tanÄ±mlÄ±yoruz:</p><pre style="text-align: justify;">
<pre class="brush: csharp">
Â Â Â  public static void RegisterRoutes(RouteCollection routes)
Â Â Â  {
        routes.MapRoute(null, &quot;{controller}/{action}&quot;);
Â Â Â  }
</pre></pre><p
style="text-align: justify;"><em>MapRoute</em> metoduna girilen ilk parametre bu yÃ¶nlendirmeye vereceÄŸimiz isim, ikinci parametre ise url pattern olmaktadÄ±r. YÃ¶nlendirmelere isim vermeye ÅŸimdilik ihtiyacÄ±mÄ±z yok. Sonraki bÃ¶lÃ¼mlerde isimlendirilmiÅŸ yÃ¶nelndirmeleri de kullanacaÄŸÄ±z.</p><h3 style="text-align: justify;">VarsayÄ±lan DeÄŸerler</h3><p
style="text-align: justify;">GirdiÄŸimiz url segmentlerinden istediklerimize varsayÄ±lan deÄŸer atayabiliriz. BÃ¶ylece o segmentin url&#8217;de belirtilmesi zorunluluÄŸunu kaldÄ±rmÄ±ÅŸ oluruz. Mesela sitemizin ana sayfasÄ± iÃ§in AnaSayfa controller sÄ±nÄ±fÄ±nÄ± ve action method olarak Index kullanalÄ±m. VarsayÄ±lan deÄŸer kullanmazsak, sitemize girilmesi iÃ§in illaki <em>http://www.diyezon.com/AnaSayfa/Index</em> girilmesi gerekirdi ki bu gÃ¼zel bir sonuÃ§ deÄŸildir. Bu gibi durumlarda segment deÄŸiÅŸkenlerine girilmedikleri yani null olduklarÄ± vakit <em>varsayÄ±lan</em> deÄŸer belirleyebiliriz.</p><pre>
<pre class="brush: csharp">
Â Â Â  public static void RegisterRoutes(RouteCollection routes)
Â Â Â  {
        routes.MapRoute(null, &quot;{controller}/{action}&quot;,
            new { action=&quot;Index&quot; });
Â Â Â  }
</pre></pre><p
style="text-align: justify;">YukarÄ±daki oluÅŸturduÄŸumuz route ile action girmez isek yani <em>http://www.diyezon.com/AnaSayfa</em> gibi bir ÅŸey girersek, action deÄŸiÅŸkeni varsayÄ±lan olarak Index olacaktÄ±r. AynÄ± ÅŸeyi controller deÄŸiÅŸkeni iÃ§in de yapabilirsiniz:</p><pre>
<pre class="brush: csharp">
Â Â Â  public static void RegisterRoutes(RouteCollection routes)
Â Â Â  {
        routes.MapRoute(null, &quot;{controller}/{action}&quot;,
            new { controller=&quot;AnaSayfa&quot;, action=&quot;Index&quot; });
Â Â Â  }
</pre></pre><p
style="text-align: justify;">Bu durumda <em>http://www.diyezon.com</em> ÅŸeklinde bir url girdiÄŸimizde AnaSayfa controller sÄ±nÄ±fÄ±ndaki Index action metodu Ã§alÄ±ÅŸtÄ±rÄ±lacaktÄ±r.</p><h3 style="text-align: justify;">URL Sabit DeÄŸerleri</h3><p
style="text-align: justify;">Bir url ÅŸablonuna sabit deÄŸerler ekleyebilirsiniz. Mesela:</p><pre>
<pre class="brush: csharp">
Â Â Â  public static void RegisterRoutes(RouteCollection routes)
Â Â Â  {
        routes.MapRoute(null, &quot;eski-makaleler/{controller}/{action}&quot;,
            new { controller=&quot;AnaSayfa&quot;, action=&quot;Index&quot; });
Â Â Â  }
</pre></pre><p
style="text-align: justify;">Bu pattern ancak &#8220;http://www.diyezon.com/eski-makaleler/&#8221; ile baÅŸlayan urller ile eÅŸleÅŸecektir. Sabit deÄŸerleri illaki bir segmente girmeniz gerekmez. Dilerseniz bir deÄŸiÅŸken ile bitiÅŸik bir ÅŸekilde kullanabilirsiniz:</p><pre>
<pre class="brush: csharp">
Â Â Â  public static void RegisterRoutes(RouteCollection routes)
Â Â Â  {
        routes.MapRoute(null, &quot;Eski{controller}/{action}&quot;,
            new { controller=&quot;AnaSayfa&quot;, action=&quot;Index&quot; });
Â Â Â  }
</pre></pre><p
style="text-align: justify;">Bu tanÄ±mlama ile http://www.diyezon.com/EskiAnaSayfa ÅŸeklinde girdiÄŸimiz bir url&#8217;de controller deÄŸiÅŸkeni yine AnaSayfa olacaktÄ±r, EskiAnaSayfa deÄŸil!</p><p
style="text-align: justify;">Yine baÅŸka bir yaklaÅŸÄ±m ile sabit deÄŸerler ve varsayÄ±lan deÄŸerler ile bir karÄ±ÅŸÄ±m yapabilirsiniz:</p><pre>
<pre class="brush: csharp">
Â Â Â  public static void RegisterRoutes(RouteCollection routes)
Â Â Â  {
        routes.MapRoute(null, &quot;Eski/{action}&quot;,
            new { controller=&quot;AnaSayfa&quot;, action=&quot;Index&quot; });
Â Â Â  }
</pre></pre><p
style="text-align: justify;">Bu durumda http://www.diyezon.com/Eski/Goster gibi bir url&#8217;de controller deÄŸiÅŸkeni yine AnaSayfa olacak ve action ise Goster olacaktÄ±r.</p><p
style="text-align: justify;">Makale henÃ¼z bitmedi. Sonraki sayfaya aÅŸaÄŸÄ±daki linklerden geÃ§ebilirsiniz.</p> ]]></content:encoded> <wfw:commentRss>http://www.diyezon.com/asp-net-mvc-proje-yonlendirme/feed/</wfw:commentRss> <slash:comments>10</slash:comments> </item> <item><title>ASP.NET MVC ve Razor&#8217;a GiriÅŸ</title><link>http://www.diyezon.com/asp-net-mvc-ve-razora-giris/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=asp-net-mvc-ve-razora-giris</link> <comments>http://www.diyezon.com/asp-net-mvc-ve-razora-giris/#comments</comments> <pubDate>Sun, 07 Aug 2011 13:19:13 +0000</pubDate> <dc:creator>Fatih Tolga Ata</dc:creator> <category><![CDATA[ASP.NET]]></category> <category><![CDATA[MVC]]></category> <category><![CDATA[asp.net]]></category> <category><![CDATA[mvc]]></category> <category><![CDATA[razor]]></category><guid
isPermaLink="false">http://www.diyezon.com/?p=278</guid> <description><![CDATA[AslÄ±nda ben web programlamada php&#8216;yi tercih eden birisiyim. Her ne kadar diÄŸer dillerde de siteler yapmÄ±ÅŸ olsam da php benim iÃ§in hep ilk tercih olmuÅŸtur. Nedendir bilemiyorum ama diÄŸer ortamlarda ve dillerde her zaman bir bahane bulmuÅŸumdur, o ortamÄ± ya da dili kullanmamak iÃ§in&#8230; Bazen barÄ±ndÄ±rdÄ±ÄŸÄ± kÄ±sÄ±tlÄ± nesne tabanlÄ± programalama Ã¶zelliklerinden dolayÄ± php&#8217;ye kÄ±zÄ±p ASP.NET [...]]]></description> <content:encoded><![CDATA[<p
style="text-align: justify;">AslÄ±nda ben web programlamada <em>php</em>&#8216;yi tercih eden birisiyim. Her ne kadar diÄŸer dillerde de siteler yapmÄ±ÅŸ olsam da <em>php</em> benim iÃ§in hep ilk tercih olmuÅŸtur. Nedendir bilemiyorum ama diÄŸer ortamlarda ve dillerde her zaman bir bahane bulmuÅŸumdur, o ortamÄ± ya da dili kullanmamak iÃ§in&#8230; Bazen barÄ±ndÄ±rdÄ±ÄŸÄ± kÄ±sÄ±tlÄ± nesne tabanlÄ± programalama Ã¶zelliklerinden dolayÄ± php&#8217;ye kÄ±zÄ±p <em>ASP.NET</em> ya da <em>java</em>&#8216;ya geÃ§meye Ã§alÄ±ÅŸtÄ±ÄŸÄ±m olmuÅŸtur da. Ama yine dÃ¶nÃ¼p dolaÅŸÄ±p kapaÄŸÄ± php&#8217;ye atmÄ±ÅŸÄ±mdÄ±r. Ã–zellikle asp.net, benim en fazla git gel yaptÄ±ÄŸÄ±m ortamlardan birisidir. O kadar Ã¶zellik barÄ±ndÄ±rmasÄ±na raÄŸmen neden asp.net&#8217;e Ä±sÄ±nanamÄ±ÅŸtÄ±m? AslÄ±nda cevabÄ± Ã§ok basit: <em>Web Forms</em>.</p><p
style="text-align: justify;">YakÄ±n zamanda, benim bu tarz Ã§ekincelerimin olduÄŸunu bilen, asp.net kullanan bir <strong>dostum</strong> beni <em>MVC</em> ve <em>Razor</em> ile tanÄ±ÅŸtÄ±rdÄ±. Ve aÃ§Ä±kcasÄ± Ã§ok etkilendiÄŸimi itiraf ediyorum. Ã‡Ã¼nkÃ¼ artÄ±k Web Forms gibi hantal olmayan, php&#8217;nin esnekliÄŸine sahip olan ve Ã¼stelik c# gibi nesne tabanlÄ± programlamada sÃ¶zÃ¼ geÃ§en bir dili kullanan bir ortam ile tanÄ±ÅŸmÄ±ÅŸtÄ±m.</p><p
style="text-align: justify;">Bu yazÄ±da MVC ve Microsoft&#8217;un yeni Ã§ocuÄŸu Razor gÃ¶rÃ¼nÃ¼m motorunu(view engine) tanÄ±tÄ±p, kÃ¼Ã§Ã¼k bir Ã¶rnek yapacaÄŸÄ±z</p><p><span
id="more-278"></span></p><h1 style="text-align: justify;">ASP.NET Web Forms&#8217;un Nesi Yok ki!?</h1><p
style="text-align: justify;">AslÄ±nda kÄ±sa cevap olarak, &#8220;fazlasÄ±&#8221; bile var denilebilir. Evet belki de Web FormlarÄ± ilk zamanlarda Ã§ok iyi bir fikirdi. Fakat gerÃ§ekte durum biraz daha karÄ±ÅŸÄ±k. GerÃ§ek hayatta Web FormlarÄ±nÄ± projelerde kullandÄ±kÃ§a bazÄ± durumlar ortaya Ã§Ä±kmÄ±ÅŸtÄ±r. Tabi bu durumlar zaman iÃ§inde bir Ã§ok kullanÄ±cÄ±nÄ±n deneyimi ile ortaya Ã§Ä±kmÄ±ÅŸ eksikliklerdir. Bu eksiklik ya da gereksiz fazlalÄ±klarÄ± ÅŸu ÅŸekilde maddelendirebiliriz:</p><ul
style="text-align: justify;"><li><strong>View State AÄŸÄ±rlÄ±ÄŸÄ±:</strong> <em>View State</em> olarak bilinen, istekler arasÄ±nda <em>durumlarÄ±</em> muhafaza etme mekanizmasÄ±, client ve server arasÄ±nda Ã§ok bÃ¼yÃ¼k boyutlarda veri transferine sebep oluyor. Bu veri boyutu, mÃ¼tevazi bir sitede bile yÃ¼zlerce kilobayta varabiliyor. Ãœstelik bu veri, gÃ¶nderilmekle kalmÄ±yor tekrar geri geliyor ve her istekte veri iletimindeki miktar katlanarak bÃ¼yÃ¼yor. Bu server Ã¼zerindeki bandwidth kullanÄ±mÄ±nÄ± artÄ±rdÄ±ÄŸÄ± gibi, sitenin yavaÅŸ tepkilerinden dolayÄ± site ziyaretÃ§ilerinin sinirlerinin bozulmasÄ±na da sebebiyet veriyor.</li><li><strong>Sayfa YaÅŸam DÃ¶ngÃ¼sÃ¼:</strong> Sayfa yaÅŸam dÃ¶ngÃ¼sÃ¼nÃ¼n Ã¶nemli bir parÃ§asÄ± olan, client yani istemci tarafÄ±ndaki <em>event</em>&#8216;lar(olaylar) ile server tarafÄ±ndaki <em>event handler</em> kodlarÄ± arasÄ±ndaki iletiÅŸim, aÅŸÄ±rÄ± derecede kompleks, karÄ±ÅŸÄ±k ve bir o kadar da narin, Ã§Ä±t kÄ±rÄ±ldÄ±m olabiliyor. Ã‡ok az geliÅŸtirici <em>View State</em> hatalarÄ± olmadan Ã§alÄ±ÅŸma zamanÄ±nda bileÅŸenlerin(kontrollerin) Ã¼zerinde dÃ¼zgÃ¼n bir ÅŸekilde deÄŸiÅŸiklik yapabiliyor ya da Ã§ok az geliÅŸtirici gizemli bir ÅŸekilde Ã§alÄ±ÅŸmayan <em>event handler</em>&#8216;larÄ± farkedebiliyor.</li><li><strong>Kod AyrÄ±mÄ± HakkÄ±ndaki YanlÄ±ÅŸ DÃ¼ÅŸÃ¼nceler:</strong> ASP.NET&#8217;in <em>code-behind</em> modeli, HTML kodlarÄ± ile uygulama kodlarÄ±nÄ± farklÄ± bir dosyada ayÄ±rmaya yarÄ±yor. Sunum kÄ±smÄ± ile uygulama kod kÄ±smÄ±nÄ± ayÄ±rdÄ±ÄŸÄ± iÃ§in bu model, oldukÃ§a alkÄ±ÅŸ getirdi ve takdir gÃ¶rdÃ¼. Fakat gerÃ§ekte, geliÅŸtiriciler sunum kodlarÄ±(<em>server kontrollerini deÄŸiÅŸtirmek gibi..</em>) ile uygulama mantÄ±k kodlarÄ±nÄ±(<em>veritabanÄ±nÄ± kodlarÄ± gibi&#8230;</em>) bu korkunÃ§ <em>code-behind</em> sÄ±nÄ±flarÄ±nda birleÅŸtirmeye baÅŸladÄ±lar. Bu da Ã§oÄŸu zaman manasÄ±z ve narin, kolay bozulan bir sonuca dÃ¶nÃ¼ÅŸmesine yol aÃ§mÄ±ÅŸtÄ±r ve aÃ§maktadÄ±r.</li><li><strong>HTML Ãœzerinde KÄ±sÄ±tlÄ± Kontrol:</strong> Server kontrolleri kendilerini HTML olarak <em>render</em> ederler yani bize sonuÃ§ HTML kodlarÄ± olarak gelir. Fakat bu Ã§oÄŸu zaman sizin istediÄŸiniz HTML kodundan gereksiz bir Ã§ok kod barÄ±ndÄ±rÄ±r. ASP.NET 4&#8242;den Ã¶nce genellikle bu Ã§Ä±ktÄ± kodu, web standartlarÄ±na uygun deÄŸildi veya bunlar Ã¼zerinde iyi bir CSS kullanÄ±mÄ±nÄ± zorlaÅŸtÄ±rÄ±yordu. AyrÄ±ca server kontrolleri Javascript tarafÄ±ndan ulaÅŸÄ±lmasÄ± zor olan, tahmin edilmesi zor ve karÄ±ÅŸÄ±k ID deÄŸerleri Ã¼retiyorlardÄ±. Her ne kadar ASP.Net 4 ile bu problemler azaltÄ±lmÄ±ÅŸsa da beklediÄŸiniz HTML&#8217;yi elde etmeniz halen sÄ±kÄ±ntÄ±lÄ± olabiliyor.</li><li><strong>ZayÄ±f Soyutlama:</strong> Web FormlarÄ± mÃ¼mkÃ¼n olduÄŸunca HTML&#8217;yi sizden gizlemeye Ã§alÄ±ÅŸÄ±r. Yeni ve Ã¶zel bir davranÄ±ÅŸÄ± tanÄ±mlamaya Ã§alÄ±ÅŸtÄ±ÄŸÄ±nÄ±zda, genellikle bu soyutlamayÄ± bozarsÄ±nÄ±z. Ki bu sizi <em>postback event</em> mekanizmasÄ±nda <em>ters mÃ¼hendislik</em> metodlarÄ± kullanmanÄ±zÄ± ya da istediÄŸiniz HTML&#8217;yi elde etmek iÃ§in duygusuz ve absÃ¼rd kodlar yazmanÄ±za sebep olur. Ben buna amele mantÄ±ÄŸÄ± kod yazmak diyorum <img
src='http://www.diyezon.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Ek olarak tÃ¼m bu soyutlama hadisesi, iÅŸin ehli web geliÅŸtiricileri iÃ§in sinir bozucu bir engelden Ã¶teye gidememektedir.</li><li><strong>DÃ¼ÅŸÃ¼k Test Edilebilirlik:</strong> Her ne kadar <em>unit-test</em> yani otomatikleÅŸtirilmiÅŸ testlere ilgim olmasa da, <em>unit-test</em> kullanan geliÅŸtiriciler iÃ§in Web FormlarÄ± bir Ã§ileden ibaret olmuÅŸtur. Web FormlarÄ±nÄ±n bu kapalÄ± hali unit testi iÃ§in uygunsuz bir durum teÅŸkil etmektedir Projeye <em>unit-test</em> dahil etmenin zorluÄŸu da cabasÄ±&#8230;</li></ul><p>Her ne kadar ASP.NET 4 ile burada bahsedilen bazÄ± problemlere Ã§Ã¶zÃ¼m getirilmeye Ã§alÄ±ÅŸÄ±lmÄ±ÅŸsa da halen Ã§oÄŸu kÄ±sÄ±tlamalar ve eksikliker aynen durumunu muhafaza etmektedir.</p><h1><span
style="color: #ff0000;">M</span>odel, <span
style="color: #ff0000;">V</span>iew, <span
style="color: #ff0000;">C</span>ontroller</h1><p
style="text-align: justify;">MVC baÅŸlÄ±ca ÅŸu Ã¼Ã§ ana daldan oluÅŸan bir yazÄ±lÄ±m geliÅŸtirme tekniÄŸidir:</p><ul><li
style="text-align: justify;"><strong>Model:</strong> Ä°letimde kullanÄ±lan ya da veritabanÄ± gibi ortamlarda kullanÄ±lan veriyi ifade eden basit sÄ±nÄ±flardÄ±r. Web programlamada bu genelde formun POST verileri ya da veritabanÄ±ndaki bir tabloyu ifade eden bir sÄ±nÄ±f olabilir. SonuÃ§ta <em>View</em> ve <em>Controller</em> arasÄ±nda veri iletimini <em>Modeller</em> ile gerÃ§ekleÅŸtirmekteyiz.</li><li
style="text-align: justify;"><strong>View:</strong> Sunum kÄ±smÄ±dÄ±r. Yani bu web prgramlama iÃ§in html sayfasÄ±dÄ±r. <em>Razor</em> sÃ¶z konusu olduÄŸunda dosya uzantÄ±sÄ± <em>&#8220;.cshtml&#8221;</em> dir. EÄŸer <em>Aspx</em> gÃ¶rÃ¼nÃ¼m motoru kullanÄ±lÄ±yorsa bu uzantÄ± <em>&#8220;.aspx&#8221;</em> olacaktÄ±r. GÃ¶rÃ¼nÃ¼m motorlarÄ±(<em>View Engine</em>) ve <em>Razor</em> hakkÄ±nda ileride daha geniÅŸÃ§e bahsedeceÄŸiz.</li><li
style="text-align: justify;"><strong>Controller:</strong> Esas iÅŸ gÃ¶ren uygulama kodlarÄ±dÄ±r. Mesela bu, form verilerini veritabanÄ±na ekleyen bir sÄ±nÄ±f olabilir. SonuÃ§ta view katmanÄ±nÄ±n kullanÄ±cÄ±ya gÃ¶sterilmesi iÃ§in gerekli iÅŸlemleri controller gerÃ§ekleÅŸtirecektir.</li></ul><p
style="text-align: justify;">Sizi Ã§ok terim ile boÄŸmak istemiyorum. Daha fazla bilgi edinmek isterseniz <a
href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank">burayÄ±</a> ziyaret edebilirisiniz.</p><p
style="text-align: justify;">Bir iletiÅŸim sayfasÄ±nÄ± gÃ¶zÃ¼mÃ¼zÃ¼n Ã¶nÃ¼ne getirelim. Ne vardÄ±r basit bir iletiÅŸim sayfasÄ±nda? Ad soyad, e-posta gibi bilgilerin girildiÄŸi bir textbox, mesajÄ±n yazÄ±lacaÄŸÄ± bir textarea ve mesajÄ±n gÃ¶nderileceÄŸi bir submit dÃ¼ÄŸmesi. Submit dÃ¼ÄŸmesine tÄ±kladÄ±ÄŸÄ±nÄ±z anda, form post edilir ve gerekli kontroller yapÄ±larak e-posta gÃ¶nderilir ya da kullanÄ±cÄ±ya hata verilir. MVC mantÄ±ÄŸÄ± ile dÃ¼ÅŸÃ¼ndÃ¼ÄŸÃ¼mÃ¼zde, iÃ§inde textbox, textarea, button bulunduran sayfamÄ±z <em>View</em> katmanÄ±dÄ±r. Form post olduktan sonra gelen verilerin uygunluÄŸunu test eden ve e-postanÄ±n gÃ¶nderimini saÄŸlayan kÄ±sÄ±m ise <em>Controller</em>&#8216;dÄ±r. <em>Model</em> ise bu iki katman arasÄ±nda gelip giden form&#8217;un post verilerinin <em>ÅŸablon</em>udur. Bu Ã¶rnek iÃ§in textboxlardaki ad soyad ve e-posta bilgileri ve textarea&#8217;daki mesaj verisi <em>Model</em> ile ifade edilir. <em></em></p><p
style="text-align: justify;"><em>Model</em> ve <em>Controller</em> &#8220;.cs&#8221; uzantÄ±lÄ± bir dosyada bulunan sÄ±nÄ±flardan ibaretken <em>View</em> &#8220;.cshtml&#8221; uzantÄ±lÄ± c# ve html kodlarÄ±nÄ±n karÄ±ÅŸÄ±k olduÄŸu bir dosyadÄ±r. Bu uzantÄ±larÄ±n C#&#8217;a ait uzantÄ±lar olduÄŸunu ifade etmek istiyorum. EÄŸer Vb.Net kullanÄ±yorsanÄ±z bu uzantÄ±lar &#8220;.vb&#8221; ve &#8220;.vbhtml&#8221; olacaktÄ±r. Veya <em>Razor</em> yerine baÅŸka bir gÃ¶rÃ¼nÃ¼m motoru kullanÄ±yorsanÄ±z &#8220;.cshtml&#8221; uzantÄ±sÄ± deÄŸiÅŸiklik gÃ¶sterecektir.</p><p
style="text-align: justify;">MVC aslÄ±nda yeni bir teknoloji olmadÄ±ÄŸÄ± gibi mucidi Microsoft da deÄŸildir. MVC, kÃ¶kleri 1978 yÄ±lÄ±na dayanan ve <em>Xerox PARC</em> da <em>Smalltalk</em> projelerinde kullanÄ±lmÄ±ÅŸ bir yÃ¶ntemdir. Fakat gÃ¼nÃ¼mÃ¼zde web programlamada ciddi Ã¶lÃ§Ã¼de popÃ¼lerlik kazanmÄ±ÅŸtÄ±r. Ã–zellikle <em>Ruby on Rails</em> ile bu had safhaya ulaÅŸmÄ±ÅŸtÄ±r. <em>Ruby on Rails</em>&#8216;in bu popÃ¼lerliÄŸi o kadar artmÄ±ÅŸtÄ±r ki Microsoft&#8217;un gÃ¶zÃ¼nÃ¼ aÃ§masÄ±na sebep olmuÅŸtur. <em>Ruby on Rails</em>&#8216;in bu baÅŸarÄ±sÄ±nÄ±, kullandÄ±ÄŸÄ± dilden Ã§ok, iÃ§ine monte edilen <em>MVC</em> ve <em>ORM</em> mimarilerine baÄŸlamak gerekir. Microsoft sadece MVC&#8217;ye el atmamÄ±ÅŸ, ayrÄ±ca bir ORM mimarisi olan Entity Framework ve beraberinde LINQ de .NET&#8217;e dahil olmuÅŸtur. Evet ORM&#8217;nin Ã¼nlÃ¼ olmasÄ±na sebep LINQ ve Entity Framework deÄŸildir aslÄ±nda.</p><p
style="text-align: justify;">Åžu an iÃ§in bir Ã§ok dilde MVC yapÄ±sÄ±nÄ± kullanan kÃ¼tÃ¼phaneler mevcuttur. Mesela php&#8217;de CakePhp, Symfony ve Mojavi MVC kÃ¼tÃ¼phanelerine en gÃ¼zel Ã¶rneklerdendir. Fakat bulabileceÄŸiniz Ã§oÄŸu MVC kÃ¼tÃ¼phanesi Rails&#8217;den esinlenmiÅŸtir.</p><p
style="text-align: justify;">Belki ÅŸu an iÃ§in kafanÄ±zda MVC ne olduÄŸuna dair somut bir fikir oluÅŸmamÄ±ÅŸ olabilir. Makelenin sonununda vereceÄŸimiz kÃ¼Ã§Ã¼k Ã¶rneÄŸi kendiniz yaparak somut fikir edineceÄŸinizi tahmin ediyorum.</p><h1>ASP.NET MVC</h1><p
style="text-align: justify;">MVC mimarisi, Web Forms mimarisinden farklÄ± bir yapÄ±ya sahiptir. Web FormlarÄ±nda tut-taÅŸÄ± mantÄ±ÄŸÄ± ile Ã§ok hÄ±zlÄ± bir ÅŸekilde siteler oluÅŸturabilirsiniz. Fakat iÅŸ yukarÄ±da da bahsettiÄŸimiz gibi Ã¶zelleÅŸtirmeye ve temiz html kodlarÄ±na geldiÄŸinde, durum biraz deÄŸiÅŸiyor. ASP.NET MVC, temiz, standartlara uyumlu html kodlarÄ± Ã¼retmenin farkÄ±ndadÄ±r. Ve barÄ±ndÄ±rdÄ±ÄŸÄ± <em>Html</em> yardÄ±mcÄ± metodlarÄ±, Web FormlarÄ±n aksine, ciddi Ã¶lÃ§Ã¼de temiz ve standart uyumlu kodlar Ã¼retirler. KÃ¼Ã§Ã¼k bir kontrol iÃ§in bile bir Ã§ok hantal ve karÄ±ÅŸÄ±k kodlar Ã¼retmek yerine, CSS ile ÅŸekillendirilmiÅŸ gayet basit ve hoÅŸ kodlar Ã¼retir.</p><p
style="text-align: justify;">Hemen akla gelen, Web FormlarÄ±ndaki gibi, kodlarÄ± hazÄ±r, menÃ¼ ve tarih seÃ§ici gibi bileÅŸenleri olsa iyi olmazmÄ±ydÄ±. Bunun iÃ§in en iyi Ã§Ã¶zÃ¼m <em>jQuery</em> gibi javascript bileÅŸenleri olacaktÄ±r. Ä°ÅŸin gerÃ§eÄŸi Web FormlarÄ± kullanÄ±rken bile Web FormlarÄ±nÄ±n varsayÄ±lan bileÅŸenleri yerine bu tarz bileÅŸenleri daha fazla kullanmaktayÄ±z. Bununla birlikte ASP.NET MVC dahili <em>jQuery</em> desteÄŸine sahiptir. EÄŸer bir fikir edinmek isterseniz <a
href="http://jqueryui.com/demos/datepicker/">buraya</a> gÃ¶z atabilirsiniz.</p><p
style="text-align: justify;">Web FormlarÄ±nÄ±n aksine, ASP.NET MVC ile Ã¼retilmiÅŸ sayfalar <em>View State</em> namÄ±na hiÃ§ bir veri iÃ§ermezler. Bu yÃ¼zden kÃ¼Ã§Ã¼k bir site iÃ§in bile yÃ¼zlerce kilobayt boyutunda olan bu hantallÄ±ktan kurtulmuÅŸ olursunuz.</p><p
style="text-align: justify;">AyrÄ±ca ASP.NET MVC mÃ¼kemmel bir yÃ¶nelendirme sistemine sahiptir. Bu sayede ÅŸu ÅŸekildeki bir urlyi:</p><pre style="text-align: justify;">/web_motoru/Makaleler/Default.aspx?islem=goster&amp;makale_id=41567&amp;sayfa=1</pre><p
style="text-align: justify;">daha temiz ve kullanÄ±cÄ±lar iÃ§in ve seo iÃ§in daha uygun bir ÅŸekle zahmetsizce Ã§evirebilirsiniz:</p><pre style="text-align: justify;">/makale/mvc-ve-razor/sayfa-1</pre><p
style="text-align: justify;">BÃ¶ylesine bir yapÄ± hem SEO iÃ§in hem kullanÄ±cÄ±lar iÃ§in hem de gÃ¼venlik iÃ§in daha kullanÄ±ÅŸlÄ± olacaktÄ±r.</p><p
style="text-align: justify;">Bunun dÄ±ÅŸÄ±nda sÃ¶yleyebileceÄŸim baÅŸka bir ÅŸey de, ASP.NET MVC&#8217;nin aÃ§Ä±k kaynak kodlu olduÄŸudur. Bunun bize getirdiÄŸi en bÃ¼yÃ¼k faydalardan biri ÅŸÃ¼phesiz debug aÅŸamasÄ±nda ortaya Ã§Ä±kmaktadÄ±r. Sistem bileÅŸenlerinin nasÄ±l Ã§alÄ±ÅŸtÄ±ÄŸÄ±nÄ± gÃ¶rebileceÄŸiniz gibi geliÅŸtiricilerin yorumlarÄ±nÄ± bile kodlarda gÃ¶rebilirsiniz.</p><p
style="text-align: justify;">BaÅŸka bir ÅŸey ise, MVC stateless dediÄŸimiz bir yapÄ±ya sahiptir. Yani Web FormlarÄ±nda olduÄŸu gibi sayfanÄ±n o anki durumu kayÄ±t altÄ±nda tutulmaz. Tersine bu yapÄ±ya tamamen karÅŸÄ± bir yapÄ±ya sahiptir. Bu yÃ¼zdendir ki Ã¶nceden bahsettiÄŸimiz gibi View State&#8217;e ihtiyaÃ§ duymaz ve kullanmaz.</p><h1>Razor</h1><p
style="text-align: justify;">Microsoft sadece MVC ve ORM mimarilerini ASP.NET ortamÄ±na taÅŸÄ±makla kalmamÄ±ÅŸ yeni bir gÃ¶rÃ¼nÃ¼m motoru da kazandÄ±rmÄ±ÅŸtÄ±r. GÃ¶rÃ¼nÃ¼m Motoru(<em>View Engine</em>), uygulama kodlarÄ± ile(bu makale iÃ§in C#), html ve benzeri text tabanlÄ± verileri iÃ§ iÃ§e kullanmanÄ±zÄ± saÄŸlar. ASP.NET MVC iÃ§in tanÄ±mlanmÄ±ÅŸ bir Ã§ok gÃ¶rÃ¼nÃ¼m motoru bulunmaktadÄ±r. BunlarÄ±n baÅŸlÄ±calarÄ±, <em>Spark</em>, <em>SharpTiles</em>, <em>NHaml</em>, <em>WebForms</em>(<em>ASPX</em>) ve <em>Razor</em>.</p><p
style="text-align: justify;">KÄ±sacasÄ±; <em>Spark</em>, html benzeri bir gramere, <em>SharpTiles</em> java kullanÄ±cÄ±larÄ±na yakÄ±n bir gramere ve <em>NHaml</em> ise Rail benzeri bir gramere sahip. <em>WebForms</em> ise bildiÄŸimiz ASPX gÃ¶rÃ¼nÃ¼m motorudur. TÃ¼m kodlar &lt;% ve %&gt; iÅŸaretleri arasÄ±na yazÄ±lÄ±r.</p><p
style="text-align: justify;"><em>Razor</em>, Microsoft tarafÄ±ndan geliÅŸtirilmiÅŸ olan yep yeni bir gramere sahip bir gÃ¶rÃ¼nÃ¼m motorudur. Yeni gramer derken sakÄ±n korkmayÄ±n. Ã‡Ã¼nkÃ¼ Razor diÄŸer gÃ¶rÃ¼nÃ¼m motorlarÄ±nda olduÄŸu gibi sizi yeni bir grameri Ã¶ÄŸrenmek zorunda <strong>bÄ±rakmaz</strong>. KullanacaÄŸÄ±nÄ±z dil yine C# gibi bir .net dili olacaktÄ±r. KÄ±saca Razor:</p><ul><li>Az yer kaplayan, kompakt, anlamlÄ± ve akÄ±cÄ± bir yapÄ±ya sahiptir.</li><li>Ã–ÄŸrenmesi Ã§ok kolaydÄ±r.</li><li>Sizi yeni bir dil Ã¶ÄŸrenmek zorunluÄŸundan kurtarÄ±r.</li><li>Ã‡ok Ã§ok iyi bir Intellisense desteÄŸi mevcuttur.</li><li>Unit-test&#8217;lerine uygun bir yapÄ±sÄ± mevcuttur.</li></ul><p>Mesela aÅŸaÄŸÄ±daki ASPX gÃ¶rÃ¼nÃ¼m motoru ile oluÅŸturulmuÅŸ kodlara bakalÄ±m:</p><pre>
<pre class="brush: csharp">
&lt;ul&gt;
&lt;% foreach (var country in Model)
   { %&gt;
        &lt;li&gt;&lt;%: country.GetCountryCode(); %&gt;&lt;/li&gt;
&lt;% } %&gt;
&lt;/ul&gt;
</pre></pre><p
style="text-align: justify;">Bu kodlarÄ±n Razor karÅŸÄ±lÄ±ÄŸÄ± ise ÅŸÃ¶yle olacaktÄ±r:</p><pre>
<pre class="brush: csharp">
&lt;ul&gt;
@foreach (var country in Model)
{
    &lt;li&gt;@country.GetCountryCode()&lt;/li&gt;
}
&lt;/ul&gt;
</pre></pre><p
style="text-align: justify;">Bilmiyorum farkettiniz mi ama C# kodu yazmak iÃ§in sadece &#8220;@&#8221; iÅŸaretini kullandÄ±k. GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi Ã§ok sade bir grameri var. Ä°lerledikÃ§e bu gramere aÅŸina olacaksÄ±nÄ±z ama bir kaÃ§ kÃ¼Ã§Ã¼k detaya deÄŸinmek istiyorum.</p><p
style="text-align: justify;">YukarÄ±daki kÃ¼Ã§Ã¼k Ã¶rnekte gÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi basit bir Razor kodunu ÅŸu ÅŸekilde yazÄ±yoruz:</p><p
style="text-align: justify;"><pre class="brush: csharp">&lt;div&gt;Ä°sminiz: @Model.Name&lt;/div&gt;</pre></p><p
style="text-align: justify;">&#8220;@&#8221; iÅŸareti ile baÅŸlayan inline kodunu herhangi bir ÅŸey ile kapatmÄ±yoruz. Bir nesnenin ya da strict sÄ±nÄ±fÄ±n bir Ã¶zelliÄŸini ya da metodunu html kodumuz iÃ§ine <em>yazdÄ±rmak</em> istiyorsak bu tarz kullanÄ±mÄ± tercih edebiliriz. GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi @ ile baÅŸlayan kod bloÄŸu, &#8220;;&#8221; veya &#8220;%&gt;&#8221; gibi herhangi bir sonlandÄ±rÄ±cÄ±ya ihtiyaÃ§ duymadan, bir satÄ±r sonlandÄ±rÄ±cÄ±sÄ±, bir text ya da html tag&#8217;Ä±nda sonlanÄ±yor.</p><p
style="text-align: justify;">Razor daha karmaÅŸÄ±k kod bloklarÄ±nÄ±n da benzer bir ÅŸekilde Ã¼stesinden gelir. Mesela bir if bloÄŸunu ele alalÄ±m:</p><pre style="text-align: justify;">
<pre class="brush: csharp">
@if (Model.WebSiteName == &quot;Diyezon&quot;)
{
    &lt;div&gt;@Model.WebSiteName sitesinin adresi: &lt;a href=&quot;@Model.WebSiteUrl&quot;&gt;@Model.WebSiteUrl&lt;/a&gt;&lt;/div&gt;
}
</pre></pre><p
style="text-align: justify;">Razor sÃ¼slÃ¼ parentez ile baÅŸlayÄ±p ve biten bu bloÄŸun iÃ§eriÄŸini C# kodu olarak kabul eder. Tabiki Razor sahip olduÄŸu akÄ±llÄ± gramer sayesinde blok iÃ§inde &lt;div&gt; ile baÅŸlayan satÄ±rÄ± C# kodu olmadÄ±ÄŸÄ±nÄ± anlar ve o satÄ±rÄ± html ya da text satÄ±rÄ± olarak algÄ±lar. Bu satÄ±r &lt;div&gt; ile baÅŸladÄ±ÄŸÄ± iÃ§in iÃ§ine yerleÅŸtireceÄŸimiz tÃ¼m C# kodlarÄ± da @ iÅŸareti ile baÅŸlamalÄ±dÄ±r.</p><p
style="text-align: justify;">YukarÄ±daki Ã¶rnekte gÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi birden fazla kod satÄ±rÄ± eklemek istediÄŸimiz durumlarda kod bloklarÄ±nÄ± kullanabiliriz. Yani:</p><pre style="text-align: justify;">
<pre class="brush: csharp">
@{
    string BirString = &quot;Bu bir string&quot;;
    int sayi = 5;
}
</pre></pre><p
style="text-align: justify;">Bir kod bloÄŸunun bir satÄ±rÄ±nÄ±n ilk terimi bir Ã¶nceki Ã¶rnekte olduÄŸu gibi bir html tag&#8217;Ä± ise(bir Ã¶nceki Ã¶rnekte &lt;div&gt; idi), Razor bu satÄ±rÄ± text ya da html satÄ±rÄ± olarak algÄ±lar. Fakat bu son Ã¶rnekte olduÄŸu gibi normal bir karakter ile baÅŸlarsa, Razor bu satÄ±rÄ± c# kod satÄ±rÄ± olarak algÄ±lar. Bu yÃ¼zden satÄ±rÄ± &#8220;;&#8221; ile sonlandÄ±rdÄ±k. Ã‡Ã¼nkÃ¼ bu satÄ±r c# kod satÄ±rÄ±.</p><p
style="text-align: justify;">Peki kod bloÄŸu iÃ§inde html tag&#8217;i olmadan dÃ¼z bir yazÄ±yÄ± nasÄ±l yazarÄ±z?</p><pre style="text-align: justify;">
<pre class="brush: html">
&lt;p&gt;
@{
    @:Normal bir yazÄ± satÄ±rÄ±&lt;br /&gt;
    &lt;text&gt;Normal bir yazÄ±
          satÄ±rÄ± daha. Ama bu sefer
          tek satÄ±r deÄŸil.&lt;/text&gt;
}
&lt;/p&gt;
</pre></pre><p
style="text-align: justify;">YukarÄ±da iki yÃ¶ntem ile de bir kod bloÄŸu iÃ§inde yazÄ± yazabiliriz. YukarÄ±daki Ã¶rnekte ikinci satÄ±rÄ±n &#8220;&lt;text&gt;&#8221; tagÄ± ile baÅŸladÄ±ÄŸÄ±na dikkat edin. Bu tag bir html tag&#8217;Ä± gibi gÃ¶zÃ¼kse de Razor&#8217;a ait Ã¶zel bir tag&#8217;dÄ±r. Ve bu tag kaynak kodda gÃ¶zÃ¼kmeyecektir. Yani yukarÄ±daki Ã¶rneÄŸin html Ã§Ä±ktÄ±sÄ± aÅŸaÄŸÄ±daki gibi olacaktÄ±r:</p><pre style="text-align: justify;">
<pre class="brush: html">
&lt;p&gt;
Normal bir yazÄ± satÄ±rÄ±&lt;br /&gt;
Normal bir yazÄ±
satÄ±rÄ± daha. Ama bu sefer
tek satÄ±r deÄŸil.
&lt;/p&gt;
</pre></pre><p
style="text-align: justify;">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi &lt;text&gt; tagÄ± Ã§Ä±ktÄ±da gÃ¶zÃ¼kmemektedir. KÄ±sacasÄ± bir kod bloÄŸunun iÃ§inde bir text ya da html satÄ±rÄ± aÃ§mak istiyorsdak &#8220;@:&#8221; ya da &#8220;&lt;text&gt;&#8221; kullanmalÄ±yÄ±z. SeÃ§im size kalmÄ±ÅŸ.</p><p
style="text-align: justify;">Razor gÃ¶rÃ¼nÃ¼m motoru tahmin ettiÄŸimizden daha akÄ±llÄ± davranÄ±r. Mesela aÅŸaÄŸÄ±daki gibi yazÄ±yÄ±:</p><pre style="text-align: justify;">
<pre class="brush: html">admin@yahoo.com</pre></pre><p
style="text-align: justify;">bir e-posta olarak algÄ±lar. Yani &#8220;yahoo&#8221; sÄ±nÄ±fÄ±nÄ±n ya da nesnesinin &#8220;com&#8221; Ã¶zelliÄŸini Ã§aÄŸÄ±rmaz. Veya aÅŸaÄŸÄ±daki gibi bir inline koduna bakalÄ±m:</p><pre style="text-align: justify;">
<pre class="brush: html">Merhaba @adSoyad. Bu gÃ¼nÃ¼n tarihi @tarih.</pre></pre><p
style="text-align: justify;">Inline kodlarÄ±n sonundaki &#8220;.&#8221; iÅŸaretine dikkat edin. Razor bunu normal text olarak algÄ±layacak kadar ve bir metod ya da Ã¶zellik Ã§aÄŸÄ±ran nokta gibi algÄ±lamayacak kadar zekidir.</p><p
style="text-align: justify;">Daha fazla ayrÄ±ntÄ±ya girip kafanÄ±zÄ± ÅŸiÅŸirmek istemiyorum. Åžimdilik bu kadarlÄ±k gramer bilgisi fazlasÄ±yla yeterli. EÄŸer daha fazla detaya inmek isterseniz <a
href="http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx" target="_blank">ÅŸuradaki</a> sitede gÃ¼zel bir tablo hazÄ±rlanmÄ±ÅŸ, mÃ¼racaat edebilirsiniz.</p><h1 style="text-align: justify;">MVC&#8217;ye HazÄ±rlÄ±k</h1><p
style="text-align: justify;">Ben ÅŸu anda Visual Web Developer 2010 Express sÃ¼rÃ¼mÃ¼nÃ¼ kullanÄ±yorum. Hem bedava hem de her ihtiyacÄ±nÄ±zÄ± karÅŸÄ±lamakta. Express sÃ¼rÃ¼mlerin eksiÄŸi unit-test hadisesi ki ben unit-test ile uÄŸraÅŸmayÄ± sevmediÄŸimi sÃ¶ylemiÅŸtim zaten. Ama kullandÄ±ÄŸÄ±nÄ±z Visual Studio sÃ¼rÃ¼mÃ¼ her ne ise Web Platform Installer ile ASP.NET MVC 3 paketini rahatlÄ±kla kurabilirsiniz. EÄŸer MVC&#8217;nin daha dÃ¼ÅŸÃ¼k bir veriyonu kurulu ise yine Web Platform Installer ile ASP.NET MVC 3 Tools Update paketini kurmalÄ±sÄ±nÄ±z.</p><p
style="text-align: justify;">Yine IIS Express ve SQL Server Express versiyonlarÄ±nÄ± da kurmanÄ±zda fayda var. IIS Express kurmanÄ±zda fayda var Ã§Ã¼nkÃ¼ ASP.NET Development Server IIS&#8217;in desteklediÄŸi SSL gibi bir Ã§ok ÅŸeyi desteklemiyor. SQL Server Express de hÃ¢keza eÄŸer veritabanÄ± kullanan bir proje geliÅŸtirecekseniz kurmanÄ±z gerekenlerden. Bu ikisi de Web Platform Installer ile sorunsuz bir ÅŸekilde kurulabilir.</p><p
style="text-align: justify;">ASP.NET MVC 3 paketini kurduÄŸunuzda Visual Studio(VS) ya da Visual Web Developerda(VWD) yeni proje ekranÄ±nda ASP.NET MVC 3 Web Application seÃ§eneÄŸini gÃ¶receksiniz. EÄŸer gÃ¶rmÃ¼yorsanÄ±z ASP.NET MVC 3 Tools Update paketini kurmamÄ±ÅŸsÄ±nÄ±z demektir.</p><h1 style="text-align: justify;">Basit Bir Ã–rnek YapalÄ±m</h1><p
style="text-align: justify;">AnlattÄ±klarÄ±mÄ±zÄ± somut bir ÅŸekilde kavrayabilmek iÃ§in basit bir Ã¶rnek yapalÄ±m. Makalenin baÅŸÄ±nda MVC&#8217;yi tarif etmek iÃ§in verdiÄŸimiz iletiÅŸim sayfasÄ± Ã¶rneÄŸini yapmaya Ã§alÄ±ÅŸalÄ±m.</p><p
style="text-align: justify;"><strong>KÃ¼Ã§Ã¼k bir not:</strong> Makale boyunca Ã§oÄŸu terimin ingilizce orjinal hallerini kullanmayÄ± tercih ettim ve ediyorum. Ã‡Ã¼nkÃ¼ VWD ya da VS&#8217;de karÅŸÄ±laÅŸacaÄŸÄ±mÄ±z terimler hep bu ÅŸekildedir. Ve bu ÅŸekilde alÄ±ÅŸmanÄ±z daha yararlÄ± olacak kanaatindeyim.</p><ol><li
style="text-align: justify;">VWD ya da VS&#8217;yi aÃ§alÄ±m ve New Project ile yeni proje aÃ§alÄ±m. Dil olarak &#8220;Visual C#&#8221;, proje template&#8217;i olarak da &#8220;ASP.NET MVC 3 Web Application&#8221; seÃ§eneÄŸini seÃ§elim. Proje adÄ± olarak &#8220;Iletisim&#8221; girelim ve pencereyi tamam&#8217;a basarak onaylayalÄ±m.</li><li
style="text-align: justify;">KarÅŸÄ±mÄ±za gelen pencereden &#8220;View engine&#8221; olarak Razor seÃ§ili olduÄŸuna dikkat edelim. Template olarak ise &#8220;Empty&#8221; seÃ§elim ve projemizi oluÅŸturalÄ±m.</li></ol><p
style="text-align: justify;">Solution Explorer&#8217;a gÃ¶z attÄ±ÄŸÄ±mÄ±zda bir kaÃ§ dosya ve klasÃ¶rÃ¼n eklendiÄŸini gÃ¶receksiniz. Åžu an iÃ§in bunlara yabancÄ± olmamÄ±z doÄŸal. Bizim iÃ§in burada en Ã¶nemli klasÃ¶rler <em>Models</em>, <em>Views</em> ve <em>Controllers</em> klasÃ¶rleridir. HiÃ§ bir ÅŸeye dokunmadan F5 ya da menÃ¼den Debug=&gt;Start Debugging ile projeyi Ã§alÄ±ÅŸtÄ±ralÄ±m. Bir kaÃ§ derleme iÅŸleminin ardÄ±ndan browser Ã¶nÃ¼mÃ¼ze gelecek ve proje sayfasÄ±nÄ± bize gÃ¶sterecek. Fakat gÃ¶receÄŸiniz gibi bir HTTP 404 hatasÄ± alacaksÄ±nÄ±z. Bunun nedeni henÃ¼z bir controller nesnemiz bulunmamasÄ±dÄ±r.</p><p
style="text-align: justify;">Bir MVC mimarisinde gelen istekler Controller nesneleri tarafÄ±ndan iÅŸlenirler. Siz bir sayfayÄ± Ã§aÄŸÄ±rdÄ±ÄŸÄ±nÄ±zda, o url&#8217;ye ait controller bu isteÄŸi alÄ±r ve iÅŸler.</p><p
style="text-align: justify;">Bir controller genelde System.Web.Mvc.Controller sÄ±nÄ±fÄ±ndan tÃ¼reyen basit bir sÄ±nÄ±ftan ibarettir. Controller iÃ§indeki her bir public metoda <em>action method</em> adÄ± verilir. Bu action metodlar web Ã¼zerinden herhangi bir url ile Ã§alÄ±ÅŸtÄ±rÄ±lÄ±rlar. Her ne kadar zorunlu olmasa da oluÅŸturduÄŸumuz controller sÄ±nÄ±flarÄ±nÄ± Controllers klasÃ¶rÃ¼ altÄ±na toplamaktayÄ±z. Åžimdi ilk controller sÄ±nÄ±fÄ±mÄ±zÄ± oluÅŸturalÄ±m.</p><ol><li
style="text-align: justify;">Solution Explorer&#8217;dan Controllers klasÃ¶rÃ¼ne saÄŸ tuÅŸla tÄ±klayalÄ±m ve Add-&gt;Controller seÃ§eneÄŸini seÃ§elim.</li><li
style="text-align: justify;">KarÅŸÄ±mÄ±za gelen Add Controller penceresinden isim olarak HomeController ismini verelim. Zaten gelen pencerede sadece &#8220;Default1&#8243; kÄ±sÄ±mÄ±nÄ± seÃ§erek burayÄ± deÄŸiÅŸtirmenizi isteyecek.</li><li
style="text-align: justify;">Template olarak Empty girelim ve tamam tuÅŸu ile onaylayÄ±p sÄ±nÄ±fÄ±mÄ±zÄ± oluÅŸturalÄ±m.</li></ol><p
style="text-align: justify;">VWD IletisimController.cs dosyasÄ±nÄ± hazÄ±rlayarak Ã¶nÃ¼mÃ¼ze sunacaktÄ±r. Hemen bir deneme yapmak iÃ§in controller sÄ±nÄ±fÄ±mÄ±zÄ± aÅŸaÄŸÄ±daki gibi dÃ¼zenleyelim:</p><pre>
<pre class="brush: csharp">
namespace Iletisim.Controllers
{
Â Â Â  public class HomeController : Controller
Â Â Â  {
Â Â Â Â Â Â Â  public string Index()
Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â  return &quot;Merhaba dÃ¼nya!&quot;;
Â Â Â Â Â Â Â  }
Â Â Â  }
}
</pre></pre><p
style="text-align: justify;">Kaydedip ctrl+shift+b ile ya da projeye saÄŸ tuÅŸla tÄ±klayÄ±p build edelim. EÄŸer browser penceresini kapatmadÄ± isek, sayfayÄ± yenileyelim. KapatmÄ±ÅŸ isek saat&#8217;in yanÄ±ndaki ASP.NET Developer Server ikonuna saÄŸ tuÅŸla tÄ±klayÄ±p Open in Web Browser seÃ§eneÄŸini seÃ§elim.</p><p
style="text-align: justify;">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi Home controller Ã§alÄ±ÅŸtÄ±rÄ±ldÄ± ve Index action metodu Ã§aÄŸrÄ±ldÄ±. SonuÃ§ta ekrana istediÄŸimiz bir text Ã§Ä±ktÄ±. SayfanÄ±n kaynak koduna bakarsanÄ±z, sadece bizim belirlediÄŸimiz string&#8217;den baÅŸka bir ÅŸey olmadÄ±ÄŸÄ±nÄ± gÃ¶receksiniz.</p><p
style="text-align: justify;">VWD yeni proje oluÅŸturduÄŸunda varsayÄ±lan olarak birincil controller ismini Home ve birincil action metodu da Index olarak atar. Yani ana sayfa ya da kÃ¶k url (&#8220;/&#8221;) Ã§aÄŸrÄ±ldÄ±ÄŸÄ±nda Home controller sÄ±nÄ±fÄ±na ait Index action metodu Ã§aÄŸrÄ±lacaktÄ±r. Ä°leride bunu nasÄ±l deÄŸiÅŸtirileceÄŸini Ã¶ÄŸreneceksiniz. Ama illaki kontrol etmek isterseniz Global.asax dosyasÄ±nda ki RegisterRoutes metoduna gÃ¶z atabilirsiniz.</p><p
style="text-align: justify;">EÄŸer Index metodunu View sayfasÄ±nÄ± gÃ¶sterecek ÅŸekilde ayarlarsak ne olacaÄŸÄ±nÄ± gÃ¶relim bunun iÃ§in Index metodunu ÅŸu ÅŸekilde deÄŸiÅŸtirin ve derleyip sayfayÄ± yenileyin:</p><pre style="text-align: justify;">
<pre class="brush: csharp">
Â Â Â Â Â Â Â  public ViewResult Index()
Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â  return View();
Â Â Â Â Â Â Â  }
</pre></pre><p
style="text-align: justify;">Derleyip sayfayÄ± yenilediÄŸinizde hata mesajlarÄ± ile karÅŸÄ±laÅŸacaksÄ±nÄ±z. Bu hata mesajlarÄ±ndan da gÃ¶receÄŸiniz gibi bu Index metoduna ait varsayÄ±lan View sayfalarÄ±nÄ±n nerelerde arandÄ±ÄŸÄ±nÄ± liste halinde gÃ¶sterilmektedir.</p><p
style="text-align: justify;">Åžimdi bu controller&#8217;Ä± dÃ¼zgÃ¼n bir ÅŸekilde gÃ¶sterecek bir view hazÄ±rlayalÄ±m. Bunun iÃ§in ilk baÅŸta sayfada hangi verilerin olacaÄŸÄ±nÄ± dÃ¼ÅŸÃ¼nmeliyiz. Bu bir iletiÅŸim sayfasÄ± olduÄŸundan basit bir kaÃ§ textbox olmasÄ± bizim iÃ§in kafi gelecektir. Controller ve View&#8217;lerde kullanÄ±lacak olan verilerin Model sÄ±nÄ±flarÄ± ile ifade edildiÄŸinden daha Ã¶nce bahsetmiÅŸtik. Bu yÃ¼zden ilk baÅŸta veri modelimizi oluÅŸturalÄ±m:</p><ol><li
style="text-align: justify;">Models klasÃ¶rÃ¼ne saÄŸ tuÅŸ ile tÄ±klayÄ±p Add-&gt;Class seÃ§eneÄŸini seÃ§elim.</li><li
style="text-align: justify;">Ä°sim olarak IletisimModel yazÄ±p entere basalÄ±m.</li><li
style="text-align: justify;">OluÅŸturulan yeni dosyayÄ± aÅŸaÄŸÄ±daki gibi dÃ¼zenleyelim:</li></ol><pre>
<pre class="brush: csharp">
namespace Iletisim.Models
{
Â Â Â  public class IletisimModel
Â Â Â  {
Â Â Â Â Â Â Â  public string AdSoyad { get; set; }
Â Â Â Â Â Â Â  public string EPosta { get; set; }
Â Â Â Â Â Â Â  public string Telefon { get; set; }
Â Â Â Â Â Â Â  public string WebSitesi { get; set; }
Â Â Â Â Â Â Â  public string Mesaj { get; set; }
Â Â Â  }
}
</pre></pre><p
style="text-align: justify;"><strong>KÃ¼Ã§Ã¼k bir ipucu:</strong> Ã–zellikleri kolay bir ÅŸekilde oluÅŸturmak iÃ§in prop yazÄ±p iki defa tab tuÅŸuna basÄ±n.</p><p
style="text-align: justify;">Åžu anda Controller ve View&#8217;lerde kullanÄ±lacak olan veri modelimizi oluÅŸturmuÅŸ bulunmaktayÄ±z. Åžimdi bu veri modeli kullanan bir View oluÅŸturalÄ±m. Tabi ilk baÅŸta daha Ã¶nce oluÅŸturmuÅŸ olduÄŸumuz controller sÄ±nÄ±fÄ±nÄ± da bu modeli kullanacak ÅŸekilde deÄŸiÅŸtirelim:</p><ol><li
style="text-align: justify;">HomeController.cs dosyasÄ±nÄ± aÃ§Ä±n.</li><li
style="text-align: justify;">HenÃ¼z deÄŸiÅŸtirmedi iseniz Index action metodunu aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirin:</li></ol><pre>
<pre class="brush: csharp">
Â Â Â Â Â Â Â  public ViewResult Index()
Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â  return View();
Â Â Â Â Â Â Â  }
</pre></pre><ol
start="3"><li
style="text-align: justify;">Ctrl+Shift+B ile projeyi derleyin.</li><li
style="text-align: justify;">Index metodunun Ã¼zerinde herhangi bir yerinde saÄŸ tuÅŸ ile tÄ±klayÄ±n ve &#8220;Add View&#8230;&#8221; seÃ§eneÄŸini seÃ§in.</li><li
style="text-align: justify;">EÄŸer Index metodunun Ã¼zerinde tÄ±kladÄ± iseniz VWD, View adÄ± olarak bu action metodunun ismini verecektir. EÄŸer View name alanÄ±nda Index yazmÄ±yorsa Index yazacak ÅŸekilde deÄŸiÅŸtirin.</li><li
style="text-align: justify;">View engine olarak yine Razor seÃ§iyoruz.</li><li
style="text-align: justify;">&#8220;Create a strongly typed view&#8221; seÃ§eneÄŸini iÅŸaretleyip altÄ±ndaki kutucuktan IletisimModel isimli modeli seÃ§elim. EÄŸer 3. adÄ±mdaki derleme iÅŸlemini yapmadÄ± iseniz yeni oluÅŸturduÄŸunuz modeli burada gÃ¶remezsiniz. Bu durumda buraya el ile Iletisim.Models.IletisimModel ÅŸeklinde model sÄ±nÄ±fÄ±nÄ±n ismini girmelisiniz.</li><li
style="text-align: justify;">Template kÄ±smÄ±nÄ± empty yani boÅŸ bÄ±rakÄ±n.</li><li>&#8220;Use a layout or master page&#8221; seÃ§eneÄŸini kaldÄ±rÄ±n. BÃ¶ylelikle herhangi bir layout veya master page kullanmamÄ±ÅŸ olacaÄŸÄ±z.</li><li
style="text-align: justify;">DiÄŸer seÃ§enekleri olduÄŸu gibi bÄ±rakÄ±n ve Add tuÅŸuna basÄ±n.</li></ol><p
style="text-align: justify;">VWD bu iÅŸlemin ardÄ±ndan Views klasÃ¶rÃ¼ne controller sÄ±nÄ±fÄ±mÄ±z ile aynÄ± isimde yani <em>Home</em> isminde bir klasÃ¶r oluÅŸturacak ve bu klasÃ¶rÃ¼n iÃ§ine <em>Index.cshtml</em> isimli bir view dosyasÄ± oluÅŸturacak.Ve bu dosyanÄ±n iÃ§eriÄŸi ÅŸÃ¶yle bir ÅŸey olacak:</p><pre>
<pre class="brush: html">
@model Iletisim.Models.IletisimModel

@{
Â Â Â  Layout = null;
}

&lt;!DOCTYPE html&gt;

&lt;html&gt;
&lt;head&gt;
Â Â Â  &lt;title&gt;Index&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Â Â Â  &lt;div&gt;

Â Â Â  &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre></pre><p
style="text-align: justify;">Ãœst kÄ±sÄ±mdaki kodlar hariÃ§ geri kalan kÄ±sÄ±m tamamen bildiÄŸimiz saf html kodlarÄ±. YukarÄ±daki @model ile baÅŸlayan ilk satÄ±r, &#8220;Create a strongly typed view&#8221; seÃ§eneÄŸi ile belirttiÄŸimiz modeli kullanacaÄŸÄ±mÄ±zÄ± ifade ediyor. SonrasÄ±nda gelen kod bloÄŸu ise herhangi bir layout ya da master page kullanmayacaÄŸÄ±mÄ±zÄ± ifade ediyor.</p><p
style="text-align: justify;">Åžimdi projeyi derleyip browser sayfasÄ±nÄ± yenileyelim. Kaynak koda baktÄ±ÄŸÄ±mÄ±zda View dosyasÄ±ndaki html kodlarÄ±nÄ±n olduÄŸunu gÃ¶receksiniz.</p><p
style="text-align: justify;">Åžu anda Ã§ok basit bir <strong>M</strong>odel-<strong>V</strong>iew-<strong>C</strong>ontroller mimarisini oluÅŸturmuÅŸ bulunmaktayÄ±z. Her ne kadar ÅŸimdilik herhangi bir iÅŸlem yapmasa da MVC mantÄ±ÄŸÄ±nÄ± daha iyi kavramamÄ±zÄ± saÄŸlayacaktÄ±r. KÄ±saca iÅŸleyiÅŸi Ã¶zetlersek; Browser&#8217;dan kullanÄ±cÄ± url&#8217;yi istekte bulunur, server bu url&#8217;ye atanmÄ±ÅŸ olan controller&#8217;Ä±n yani Ã¶rneÄŸimize gÃ¶re Home controller&#8217;Ä±n iÃ§indeki Index action metodunu Ã§aÄŸÄ±rÄ±r. ArdÄ±ndan bu action metod, kendisine ait olan View sayfasÄ±nÄ± belirlenen veri modelini kullanarak Ã§aÄŸÄ±rÄ±r ve kullanÄ±cÄ±ya Ã§Ä±ktÄ± olarak gÃ¶nderir.</p><p>Åžimdi bu sayfamÄ±zÄ± iÅŸler hale getirelim.</p><ol><li>Â Index.cshtml view dosyasÄ±nÄ± aÃ§alÄ±m ve iÃ§eriÄŸini aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim(Kendi elinizle dÃ¼zenlemenizi ÅŸiddetle tavsiye ediyorum.):</li></ol><pre>
<pre class="brush: html">
@model Iletisim.Models.IletisimModel

@{
Â Â Â  Layout = null;
}

&lt;!DOCTYPE html&gt;

&lt;html&gt;
&lt;head&gt;
Â Â Â  &lt;title&gt;Ä°letiÅŸim SayfasÄ±&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Â Â Â  @using (Html.BeginForm())
Â Â Â  {
Â Â Â Â Â Â Â  &lt;table border=&quot;0&quot;&gt;
Â Â Â Â Â Â Â  &lt;tr&gt;&lt;th&gt;Ad, Soyad: &lt;/th&gt;&lt;td&gt;@Html.TextBoxFor(m =&gt; m.AdSoyad)&lt;/td&gt;&lt;/tr&gt;
Â Â Â Â Â Â Â  &lt;tr&gt;&lt;th&gt;E-Posta: &lt;/th&gt;&lt;td&gt;@Html.TextBoxFor(m =&gt; m.EPosta)&lt;/td&gt;&lt;/tr&gt;
Â Â Â Â Â Â Â  &lt;tr&gt;&lt;th&gt;Telefon: &lt;/th&gt;&lt;td&gt;@Html.TextBoxFor(m =&gt; m.Telefon)&lt;/td&gt;&lt;/tr&gt;
Â Â Â Â Â Â Â  &lt;tr&gt;&lt;th&gt;Websitesi: &lt;/th&gt;&lt;td&gt;@Html.TextBoxFor(m =&gt; m.WebSitesi)&lt;/td&gt;&lt;/tr&gt;
Â Â Â Â Â Â Â  &lt;tr&gt;&lt;th&gt;Mesaj: &lt;/th&gt;&lt;td&gt;@Html.TextAreaFor(m =&gt; m.Mesaj)&lt;/td&gt;&lt;/tr&gt;
Â Â Â Â Â Â Â  &lt;/table&gt;
Â Â Â Â Â Â Â  &lt;input type=&quot;submit&quot; value=&quot;GÃ¶nder&quot; /&gt;
Â Â Â  }
&lt;/body&gt;
&lt;/html&gt;
</pre></pre><p
style="text-align: justify;"><em>KÃ¼Ã§Ã¼k bir ipucu:</em> View dosyalarÄ±nda yaptÄ±ÄŸÄ±nÄ±z deÄŸiÅŸiklikleri gÃ¶rmek iÃ§in projeyi tekrar derlemenize gerek yok. Browser&#8217;dan direk olarak sayfayÄ± tazelemeniz yeterli olacaktÄ±r.</p><ol
start="2"><li
style="text-align: justify;">Home controller sÄ±nÄ±fÄ±mÄ±za geÃ§elim ve aÅŸaÄŸÄ±daki deÄŸiÅŸiklikleri yapalÄ±m:</li></ol><pre>
<pre class="brush: csharp">
namespace Iletisim.Controllers
{
Â Â Â  public class HomeController : Controller
Â Â Â  {
Â Â Â Â Â Â Â  [HttpGet]
Â Â Â Â Â Â Â  public ViewResult Index()
Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â  return View();
Â Â Â Â Â Â Â  }

Â Â Â Â Â Â Â  [HttpPost]
Â Â Â Â Â Â Â  public ViewResult Index(IletisimModel iletisimModel)
Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â  return View(&quot;Tesekkur&quot;, iletisimModel);
Â Â Â Â Â Â Â  }
Â Â Â  }
}
</pre></pre><p
style="text-align: justify;"><strong>KÃ¼Ã§Ã¼k bir ipucu:</strong> EÄŸer IletisimModel sÄ±nÄ±fÄ±nÄ± bulamadÄ±ÄŸÄ±ndan dolayÄ± altÄ± kÄ±rmÄ±zÄ± ile Ã§izilirse, klavye imlecini buraya getirin ve ctrl+nokta tuÅŸlarÄ±na basÄ±n. <em>Intellisense</em> sizin iÃ§in bu sÄ±nÄ±fÄ± arayacak ve <em>using</em> ile referansÄ± ekleminizi saÄŸlayacaktÄ±r.</p><p
style="text-align: justify;">Buraya kadar ne yaptÄ±ÄŸÄ±mÄ±za bir gÃ¶z atalÄ±m.</p><p
style="text-align: justify;">Ä°lk adÄ±mÄ±mÄ±zda view sayfamÄ±zda bir form oluÅŸturduk. Bunun iÃ§in <em>Html</em> yardÄ±mcÄ± metodlarÄ±ndan yararlandÄ±k. BunlarÄ± kullanmak zorunda deÄŸildik fakat ileride kullandÄ±kÃ§a gÃ¶receÄŸiniz gibi bu yardÄ±mcÄ± metodlar model sÄ±nÄ±fÄ± ile birlikte Ã§alÄ±ÅŸarak iÅŸlemlerimizi daha da kolaylaÅŸtÄ±rÄ±yor.</p><p
style="text-align: justify;">Bu yardÄ±mcÄ± metodlardan ilki, bir html formu oluÅŸturmamÄ±za yarayan <em>Html.BeginForm()</em> metodudur. Bu metod diÄŸerlerinden farklÄ± olarak <em>using</em> kelimesi ile beraber kullanÄ±lÄ±yor. BÃ¶ylece <em>using</em> kod bloÄŸu iÃ§indeki tÃ¼m kodlar, <em>form</em> elementinin iÃ§ine yerleÅŸtiriliyorlar. SayfayÄ± browser&#8217;dan yenileyip kodlarÄ±na baktÄ±ÄŸÄ±nÄ±zda, gÃ¶receÄŸiniz gibi using kod bloÄŸunun baÅŸlangÄ±cÄ±nda form elementinin baÅŸlangÄ±Ã§ tag&#8217;Ä±(&lt;form&gt;) ve kod bloÄŸunun bitiÅŸinde de form elementinin bitiÅŸ tag&#8217;Ä±(&lt;/form&gt;) yer almaktadÄ±r. Bu metodun diÄŸer paremetre ve ayarlarÄ±na burada deyinmeyeceÄŸim. Ama tek sÃ¶yleyeceÄŸim bu metod varsayÄ±lan olarak form elementinin POST veri gÃ¶nderecek ÅŸekilde ayarladÄ±ÄŸÄ±dÄ±r. Zaten kaynak kodlara baktÄ±ÄŸÄ±nÄ±zda siz de bunu farkedeceksiniz.</p><p
style="text-align: justify;">Html.TextBoxFor() ve Html.TextAreaFor() metodlarÄ± ise paremetre olarak <em>delegate</em> tipinde veri alÄ±yor. Bu metodlara paremetre olarak <em>lambda</em> kullanÄ±larak model yapÄ±mÄ±za ait Ã¶zellikler ile iliÅŸkilendirme yapÄ±yoruz. Burada delegate kullanmamak iÃ§in TextBox() ve TextArea() metodlarÄ± da kullanÄ±labilir fakat bu ÅŸekilde model yapÄ±mÄ±za bu form elementlerini baÄŸlamamÄ±z biraz daha uzun olacaktÄ±r. Ãœstelik delegate ve lambda kullanarak yazÄ±m yanlÄ±ÅŸlarÄ±nÄ±n da Ã¶nÃ¼ne geÃ§miÅŸ oluyoruz. Ã–zellikle ilk maddede bu kodlarÄ± kendi elinizle yazmanÄ±zÄ± istememin esas sebebi bu idi. &#8220;(m =&gt; m.&#8221; yazdÄ±ktan sonra intellisense&#8217;in Ã§Ä±kardÄ±ÄŸÄ± listenin, daha Ã¶nce tanÄ±mlamÄ±ÅŸ olduÄŸumuz Model sÄ±nÄ±fÄ±na ait olduÄŸuna dikkat edin.</p><p
style="text-align: justify;">Ä°kinci adÄ±mda ise controller sÄ±nÄ±fÄ±mÄ±za baÅŸka bir Index metodu daha ekledik. Ve bu metodlardan ilkini <em>HttpGet</em> ve diÄŸerini <em>HttpPost</em> Ã¶znitelikleri(attribute) ile ilÅŸikilendirdik. BÃ¶ylelikle GET ile gelen bir istek ilk Index metodunu, POST ile gelen bir istek ise ikinci Index metodunu Ã§alÄ±ÅŸtÄ±racaktÄ±r. BildiÄŸiniz gibi her hangibir url&#8217;yi browser&#8217;dan talep ettiÄŸimizde browser server&#8217;dan GET ile istekte bulunur. Yani bu Ã¶rneÄŸimize gÃ¶re, kullanÄ±cÄ± sitenin url&#8217;sini browser&#8217;a yazÄ±p entere bastÄ±ÄŸÄ±nda ilk Index metodu Ã§alÄ±ÅŸacaktÄ±r. Velevki herhangi bir form verisi sayfaya POST edilirse, bu durumda HttpPost ile iliÅŸkilendirilmiÅŸ olan ikinci Index metodu Ã§alÄ±ÅŸtÄ±rÄ±lacaktÄ±r. View sayfamÄ±zda oluÅŸturmuÅŸ olduÄŸumuz form elementi POST veri yolladÄ±ÄŸÄ±nda, ikinci Index metodu faaliyete geÃ§ecektir.</p><p
style="text-align: justify;">Burada ikinci Index metodundaki View sayfasÄ±nÄ± Ã§aÄŸÄ±ran <em></em><em>View()</em> metoduna dikkat edin. Bu <em>View()</em> metodu, bu action metoda ait view sayfasÄ±nÄ± deÄŸil baÅŸka bir view sayfasÄ±nÄ± Ã§aÄŸÄ±rmanÄ±zÄ± saÄŸlar.Â  Bunun gibi View metodunun bir Ã§ok overload versiyonlarÄ± vardÄ±r. TÃ¼m bu overload edilmiÅŸ metod Ã§eÅŸitleri iÃ§in yardÄ±m dosyasÄ±na ya da Intellisense yardÄ±mÄ±na bakabilirsiniz. Biz bu Ã¶rneÄŸimizde view sayfasÄ±na belirlediÄŸimiz modeli parametre olarak yollayan metodu kullanmayÄ± seÃ§tik.</p><p
style="text-align: justify;">Projeyi derleyip browser&#8217;da sayfayÄ± yenileyin ve form&#8217;daki GÃ¶nder dÃ¼ÄŸmesine basÄ±n. KarÅŸÄ±lÄ±k olarak &#8220;Tesekkur&#8221; view dosyasÄ±nÄ±n bulunamadÄ±ÄŸna dair bir hata mesajÄ± alacaksÄ±nÄ±z. Buradan varsayÄ±lan olarak nerelerde bu dosya arandÄ±ÄŸÄ±nÄ± liste halinde gÃ¶rebilirsiniz. Bu view sayfasÄ±nÄ± da oluÅŸturup ekrana teÅŸekkÃ¼r mesajÄ± yazdÄ±ralÄ±m:</p><ol><li
style="text-align: justify;">Home controller dosyasÄ±nda herhangi bir yerde saÄŸ tuÅŸ ile yÄ±klayÄ±n ve &#8220;Add View..&#8221; seÃ§eneÄŸini seÃ§in.</li><li
style="text-align: justify;">View name olarak <em>Tesekkur</em> girelim.</li><li
style="text-align: justify;">&#8220;Create a strongly typed view&#8221; seÃ§ili olacak ÅŸekilde Model class olarak yine IletisimModel modelini seÃ§elim.</li><li
style="text-align: justify;">Template&#8217;i empty girelim ve yine &#8220;use a layout or master page&#8221; seÃ§eneÄŸini kaldÄ±rÄ±p Add tuÅŸuna basalÄ±m.</li><li
style="text-align: justify;">Tesekkur view dosyasÄ±nÄ± aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim:</li></ol><pre>
<pre class="brush: html">
@model Iletisim.Models.IletisimModel

@{
Â Â Â  Layout = null;
}

&lt;!DOCTYPE html&gt;

&lt;html&gt;
&lt;head&gt;
Â Â Â  &lt;title&gt;TeÅŸekkÃ¼r ederiz!&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Â Â Â  &lt;div&gt;
Â Â Â Â Â Â Â  &lt;p&gt;SayÄ±n @Model.AdSoyad,&lt;/p&gt;
Â Â Â Â Â Â Â  &lt;p&gt;Bizimle irtibata geÃ§tiÄŸiniz iÃ§in teÅŸekkÃ¼r ederiz.
Â Â Â Â Â Â Â  Size en kÄ±sa zamanda @Model.EPosta e-posta adresinizden
Â Â Â Â Â Â Â  ya da @Model.Telefon nolu telefonunuzdan ulaÅŸacaÄŸÄ±z.&lt;/p&gt;
Â Â Â Â Â Â Â  &lt;p&gt;Ä°yi gÃ¼nler.&lt;/p&gt;
Â Â Â  &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre></pre><p
style="text-align: justify;">Åžimdi bu ÅŸekilde projemizi derleyip sonucu browser&#8217;da gÃ¶zlemleyelim. Formda ki textboxlara bir ÅŸeyler yazalÄ±m ve GÃ¶nder tuÅŸuna basalÄ±m.</p><p
style="text-align: justify;">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi &#8220;Tessekkur&#8221; view dosyamÄ±z hazÄ±rladÄ±ÄŸÄ±mÄ±z gibi ekrana basÄ±ldÄ±. Fakat henÃ¼z controller sÄ±nÄ±fÄ±mÄ±z, formdan gelen bu verileri iÅŸleyecek durumda deÄŸil. Ä°lk baÅŸta form verilerinin uygunluÄŸu kontrol edilmeli. Bunun iÃ§in <em>validation</em> yani doÄŸrulama kontrolÃ¼ yapmamÄ±z gerek.</p><ol><li
style="text-align: justify;">IletisimModel isimli model sÄ±nÄ±fÄ±mÄ±za aÅŸaÄŸÄ±daki gibi eklemeler yapalÄ±m:</li></ol><pre>
<pre class="brush: csharp">
Â Â Â  public class IletisimModel
Â Â Â  {
Â Â Â Â Â Â Â  [Required(ErrorMessage=&quot;AdÄ±nÄ±z ve soyadÄ±nÄ±z gerekli.&quot;)]
Â Â Â Â Â Â Â  public string AdSoyad { get; set; }

Â Â Â Â Â Â Â  [Required(ErrorMessage=&quot;Bir e-posta adresi girmelisiniz.&quot;)]
Â Â Â Â Â Â Â  [RegularExpression(&quot;.+\\@.+\\..+&quot;,
Â Â Â Â Â Â Â Â Â Â Â  ErrorMessage=&quot;GirdiÄŸiniz e-posta geÃ§erli deÄŸil.&quot;)]
Â Â Â Â Â Â Â  public string EPosta { get; set; }

Â Â Â Â Â Â Â  [Required(ErrorMessage=&quot;Bir telefon girmelisiniz.&quot;)]
Â Â Â Â Â Â Â  public string Telefon { get; set; }

Â Â Â Â Â Â Â  public string WebSitesi { get; set; }

Â Â Â Â Â Â Â  [Required(ErrorMessage=&quot;Bir mesaj girmelisiniz.&quot;)]
Â Â Â Â Â Â Â  [StringLength(500, MinimumLength=10,
Â Â Â Â Â Â Â Â Â Â Â  ErrorMessage=&quot;GirdiÄŸiniz mesaj 10 ila 500 karakter arasÄ±nda olabilir.&quot;)]
Â Â Â Â Â Â Â  public string Mesaj { get; set; }
Â Â Â  }</pre></pre><ol
start="2"><li
style="text-align: justify;">Home controller dosyasÄ±nÄ± aÃ§alÄ±m ve <em>HttpPost</em> Ã¶znitelikli Index metodumuzu ÅŸu ÅŸekilde deÄŸiÅŸtirelim:</li></ol><pre>
<pre class="brush: csharp">
        [HttpPost]
Â Â Â Â Â Â Â  public ViewResult Index(IletisimModel iletisimModel)
Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â  if (ModelState.IsValid)
Â Â Â Â Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  return View(&quot;Tesekkur&quot;, iletisimModel);
Â Â Â Â Â Â Â Â Â Â Â  }
Â Â Â Â Â Â Â Â Â Â Â  else
Â Â Â Â Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  return View();
Â Â Â Â Â Â Â Â Â Â Â  }
Â Â Â Â Â Â Â  }
</pre></pre><ol
start="3"><li>Â Son olarak Index view dosyamÄ±zÄ± aÃ§Ä±p ÅŸu deÄŸiÅŸikliÄŸi yapalÄ±m:</li></ol><pre>
<pre class="brush: html">
&lt;body&gt;
Â Â Â  @Html.ValidationSummary()&lt;br /&gt;
Â Â Â  @using (Html.BeginForm())
Â Â Â  {
Â Â Â Â Â Â Â  &lt;table border=&quot;0&quot;&gt;
</pre></pre><p
style="text-align: justify;">Projemizi derleyelim ve browser ile sayfamÄ±zÄ± tazeleyelim. Sonucu gÃ¶zlemlemek iÃ§in textboxlarÄ± boÅŸ bÄ±rakalÄ±m ve formu gÃ¶nderelim.</p><p
style="text-align: justify;">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi Tesekkur view sayfasÄ± yerine tekrar Index&#8217;e dÃ¶ndÃ¼k. E-posta ve mesaj alanlarÄ± haricindekileri dÃ¼zgÃ¼n bir ÅŸekilde dolduralÄ±m ve e-posta alanÄ±na e-posta adresi olmayan bir ÅŸey girelim ve mesaj alanÄ±na da 10 karakterden az bir ÅŸeyler yazalÄ±m ve formu gÃ¶nderelim. Bu sefer de belirlediÄŸimiz diÄŸer doÄŸrulama mesajlarÄ±nÄ± gÃ¶receksiniz.</p><p
style="text-align: justify;">Ä°lk maddeden baÅŸlayarak kodlarÄ±mÄ±zÄ± aÃ§Ä±klayalÄ±m. Ä°lk maddede model sÄ±nÄ±fÄ±mÄ±za bazÄ± Ã¶znitelikler(attribute) ekledik. Bunlar <em>System.ComponentModel.DataAnnotations</em> alanÄ±nda tanÄ±mlÄ±dÄ±rlar. Bu yÃ¼zden eÄŸer bu Ã¶znitelikleri yazdÄ±ÄŸÄ±nÄ±zda altlarÄ± kÄ±rmÄ±zÄ± ile Ã§izilirse using ile bu alanÄ± tanÄ±tmalÄ±sÄ±nÄ±z (ya da ctrl+nokta ile otomatik eklettirebilirsiniz). Bu alan altÄ±nda doÄŸrulama yapabileceÄŸiniz bir Ã§ok Ã¶znitelik mevcutur. Biz burada bir kaÃ§Ä±nÄ± gÃ¶sterdik. En basit doÄŸrulama Ã¶zniteliÄŸi <em>Required</em> Ã¶zniteliÄŸidir ve <em>gerekli</em> manasÄ±nda olup alanÄ±n boÅŸ olup olmadÄ±ÄŸÄ±nÄ± kontrol eder. Yine <em>ReqularExpression</em> ile e-posta&#8217;nÄ±n uygun olup olmadÄ±ÄŸÄ±nÄ± kontrol iÃ§in bir regexp tanÄ±mladÄ±k. Buraya yazdÄ±ÄŸÄ±mÄ±z regular expression bizim makalemizin konusu deÄŸil. AynÄ± ÅŸekilde <em>StringLength</em> ile alanÄ±n karakter boyutunu sÄ±nÄ±rlandÄ±rmÄ±ÅŸ olduk.</p><p
style="text-align: justify;">Ä°kinci maddede ise controller sÄ±nÄ±fÄ±mÄ±zdaki HttpPost ile iliÅŸkilendirilmiÅŸ olan Index metodumuz model verilerinin doÄŸru olup olmadÄ±ÄŸÄ±nÄ± Ã¶ÄŸreniyor. Sonucunda doÄŸru deÄŸilse form yani Index view dosyasÄ± tekrar gÃ¶steriliyor. Bunun iÃ§in kullanÄ±lan Ã¶zellik <em>ModelState.IsValid</em> Ã¶zelliÄŸidir.</p><p
style="text-align: justify;">En son olarak hata mesajlarÄ±nÄ± formumuz Ã¼zerinde gÃ¶strermek iÃ§in <em>@Html.ValidationSummary()</em> metodundan faydalandÄ±k. EÄŸer sayfanÄ±n kaynak koduna bakarsanÄ±z textbox&#8217;lara da bazÄ± class deÄŸerleri eklendiÄŸini gÃ¶rebilirsiniz. Bu sayede, biz burada yapmadÄ±k ama, hatalÄ± giriÅŸ yapÄ±lmÄ±ÅŸ textboxlarÄ± css ile belirtebilirsiniz.</p><p
style="text-align: justify;">Tabi ki bu doÄŸrulama en basit ve varsayÄ±lan ÅŸekliyle karÅŸÄ±mÄ±zda. Fakat daha karmaÅŸÄ±k doÄŸrulamalarÄ± da MVC ile Ã§ok rahat bir ÅŸekilde yapabiliyorsunuz. Hatta view sayfasÄ±na eklediÄŸimiz hata mesajlarÄ±nÄ±n yapÄ±sÄ±nÄ± bile Ã§ok rahat bir ÅŸekilde deÄŸiÅŸtirebilirsiniz.</p><p
style="text-align: justify;">AslÄ±nda Ã¶rneÄŸimizin MVC ile ilgili kÄ±smÄ± bitmiÅŸ durumda. Fakat en son olarak mail gÃ¶nderme iÅŸlemini de kodlarÄ±mÄ±za ekleyelim ve projemizi tamamlamÄ±ÅŸ olalÄ±m. Tesekkur view dosyasÄ±nÄ± aÃ§alÄ±m ve aÅŸaÄŸÄ±daki eklemeleri yapalÄ±m:</p><pre>
<pre class="brush: html">
&lt;/head&gt;
&lt;body&gt;
Â Â Â  @{
Â Â Â Â Â Â Â  try
Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â  WebMail.SmtpServer = &quot;smtp.birsunucu.com&quot;;
Â Â Â Â Â Â Â Â Â Â Â  WebMail.UserName = &quot;kullanÄ±cÄ± adÄ±&quot;;
Â Â Â Â Â Â Â Â Â Â Â  WebMail.Password = &quot;ÅŸifre&quot;;
Â Â Â Â Â Â Â Â Â Â Â  WebMail.From = &quot;iletisimformu@deneme.com&quot;;
Â Â Â Â Â Â Â Â Â Â Â  WebMail.Send(&quot;info@deneme.com&quot;, &quot;Ä°letiÅŸim Formu MesajÄ±&quot;, @&lt;text&gt;
Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;p&gt;AÅŸaÄŸÄ±da bilgileri bulunan ÅŸahÄ±s iletiÅŸim formunu doldurmuÅŸtur&lt;/p&gt;
Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;p&gt;AdÄ± SoyadÄ±: @Model.AdSoyad&lt;/p&gt;
Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;p&gt;E-Posta: @Model.EPosta&lt;/p&gt;
Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;p&gt;Telefon: @Model.Telefon&lt;/p&gt;
Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;p&gt;Web Sitesi: @Model.WebSitesi&lt;/p&gt;
Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;p&gt;Mesaj: @Model.Mesaj&lt;/p&gt;
Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;/text&gt;);
Â Â Â Â Â Â Â Â Â Â Â  }
Â Â Â Â Â Â Â  catch (Exception)
Â Â Â Â Â Â Â  {
Â Â Â Â Â Â Â Â Â Â Â  @:&lt;strong&gt;E-posta gÃ¶nderirken bir hata ile karÅŸÄ±laÅŸtÄ±k. LÃ¼tfen daha sonra tekrar deneyiniz.&lt;/strong&gt;
Â Â Â Â Â Â Â  }
Â Â Â  }
Â Â Â  &lt;div&gt;
Â Â Â Â Â Â Â  &lt;p&gt;SayÄ±n @Model.AdSoyad,&lt;/p&gt;
</pre></pre><p
style="text-align: justify;">BaÅŸka ÅŸekillerde de e-posta gÃ¶nderimi yapÄ±labilir. Biz burada view iÃ§inde mail gÃ¶ndermeye Ã§alÄ±ÅŸtÄ±k fakat controller iÃ§inde de bu gÃ¶nderim yapÄ±labilir. Buradaki amacÄ±m daha Ã§ok Razor gramerine aÅŸinalÄ±ÄŸÄ±nÄ±zÄ± artÄ±rmaktÄ±r. Ã–zellikle WebMail.Send metoduna girdiÄŸimiz Ã¼Ã§Ã¼ncÃ¼ parametreye dikkat ediniz.</p><p
style="text-align: justify;">Ä°nanÄ±yorum MVC ve Razor&#8217;u benim kadar sevdiniz. Benden ÅŸimdilik bu kadar, yorumlarÄ±nÄ±zÄ± bekliyorum.</p><p
style="text-align: justify;">Ä°lerleyen zamanlarda baÅŸka MVC makaleleri ile karÅŸÄ±nÄ±zda olabilirim. Klavyenize zeval gelmesin !</p><p><strong>Fatih Tolga Ata Â© 2011</strong></p> ]]></content:encoded> <wfw:commentRss>http://www.diyezon.com/asp-net-mvc-ve-razora-giris/feed/</wfw:commentRss> <slash:comments>14</slash:comments> </item> <item><title>7 AdÄ±mda Delphi UygulamalarÄ±nÄ± Daha da HÄ±zlandÄ±rÄ±n</title><link>http://www.diyezon.com/7-adimda-delphi-uygulamalarini-daha-da-hizlandirin/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=7-adimda-delphi-uygulamalarini-daha-da-hizlandirin</link> <comments>http://www.diyezon.com/7-adimda-delphi-uygulamalarini-daha-da-hizlandirin/#comments</comments> <pubDate>Tue, 24 Feb 2009 03:58:47 +0000</pubDate> <dc:creator>Fatih Tolga Ata</dc:creator> <category><![CDATA[Delphi]]></category> <category><![CDATA[optimizasyon]]></category> <category><![CDATA[performans]]></category><guid
isPermaLink="false">http://www.diyezon.com/?p=256</guid> <description><![CDATA[Delphi, etkili ve hÄ±zlÄ± sonuÃ§ alabileceÄŸiniz nadir geliÅŸtirme ortamlarÄ±ndan birisi. Delphi&#8217;nin hÄ±zlÄ± program geliÅŸtirme Ã¶zelliÄŸi, bazen bizlerin mÃ¼srif davranmasÄ±na yol aÃ§abiliyor. AslÄ±nda birazdan vereceÄŸim adÄ±mlardan bazÄ±larÄ±, Ã§oÄŸu programlama dillerinde dikkat etmemiz gereken kurallardan. UygulamayÄ± daÄŸÄ±tmadan Ã¶nce hÄ±z iÃ§in dikkat etmemiz gerekenleri 7 adÄ±mda toplayÄ±p sizlere sunuyorum. Otomatik Form OluÅŸturmayÄ±n: Normalde, projeye eklediÄŸiniz her bir form [...]]]></description> <content:encoded><![CDATA[<p
style="text-align: justify;">Delphi, etkili ve hÄ±zlÄ± sonuÃ§ alabileceÄŸiniz nadir geliÅŸtirme ortamlarÄ±ndan birisi. Delphi&#8217;nin hÄ±zlÄ± program geliÅŸtirme Ã¶zelliÄŸi, bazen bizlerin mÃ¼srif davranmasÄ±na yol aÃ§abiliyor. AslÄ±nda birazdan vereceÄŸim adÄ±mlardan bazÄ±larÄ±, Ã§oÄŸu programlama dillerinde dikkat etmemiz gereken kurallardan. UygulamayÄ± daÄŸÄ±tmadan Ã¶nce hÄ±z iÃ§in dikkat etmemiz gerekenleri 7 adÄ±mda toplayÄ±p sizlere sunuyorum.</p><p><span
id="more-256"></span></p><ol
style="text-align: justify;"><li><strong>Otomatik Form OluÅŸturmayÄ±n: </strong>Normalde, projeye eklediÄŸiniz her bir form uygulama tarafÄ±ndan otomatik olarak oluÅŸturulmak Ã¼zere ayarlÄ±dÄ±r. Bunu dpr dosyasÄ±nÄ±n kaynak kodunda bulunan Application.CreateForm ile gÃ¶rebilrisiniz. Her ne kadar bu size formlara eriÅŸirken bÃ¼yÃ¼k kolaylÄ±k saÄŸlasa da uygulamanÄ±n ilk Ã§alÄ±ÅŸma zamanÄ±nÄ± Ã¶nemli derece de yavaÅŸlatmaktadÄ±r. Bu yÃ¼zden formlarÄ± otomatik olarak oluÅŸturmayÄ±n. Sadece ihtiyacÄ±nÄ±z olduÄŸunda dinamik olarak oluÅŸturun. Ã‡oÄŸu zaman sadece ana formu otomatik olarak oluÅŸturmanÄ±z kafi glecektir.</li><li><strong>MÃ¼mkÃ¼n OlduÄŸunca Windows API&#8217;lerini Tercih Edin:</strong> YapacaÄŸÄ±nÄ±z bir iÅŸlem iÃ§in eÄŸer Windows API&#8217;lerinde bu iÅŸi gÃ¶re bir fonksiyon var ise, sakÄ±n ayrÄ± bir fonksiyon yazmaya kalkmayÄ±n. Windows fonksiyonlarÄ±nÄ± kullanmak bizim iÃ§in en hÄ±zlÄ± yÃ¶ntem olacaktÄ±r. Bu yÃ¼zden bir fonksiyon yazmadan Ã¶nce Windows API&#8217;si iÃ§inde bu iÅŸi yapan baÅŸka bir fonksiyonun olup olmadÄ±ÄŸÄ±ndan emin olun.</li><li><strong>KÃ¼Ã§Ã¼k Fonskiyonlar Ä°Ã§in &#8220;inline&#8221; Direktifini KullanÄ±n:</strong> Yeni Delphi sÃ¼rÃ¼mleri &#8220;inline&#8221; direktifini desteklemektedir. &#8220;inline&#8221; kullanmak exe boyutunu artÄ±racaktÄ±r. Fakat hÄ±z da artacaktÄ±r. EÄŸer kÃ¼Ã§Ã¼k fonskiyonlarÄ±nÄ±z varsa veya bÃ¼yÃ¼k olsa da Ã§ok fazla yerde kullanÄ±lmayan fonksiyonlarÄ±nÄ±z varsa, fonksiyon veya prosedÃ¼r tanÄ±mlamasÄ±ndan sonra &#8220;inline&#8221; direktifini kullanÄ±n.</li><li><strong>Table yerine Query TarzÄ± BileÅŸenler KullanÄ±n:</strong> TTable gibi bileÅŸenleri mÃ¼mkÃ¼n olduÄŸunca kullanmaktan Ã§ekinin. Bunun yerine TQuery veya TSqlQuery tarzÄ± bileÅŸenleri tercih edin.</li><li><strong>FastMM KullanÄ±n:</strong> FastMM projesi, normalde Delphi 2005 ile Delphi&#8217;ye dahil oldu. EÄŸer daha dÃ¼ÅŸÃ¼k versiyon kullanÄ±yorsanÄ±z kesinlikle FastMM kullanÄ±n. D2005 ve yukarÄ±sÄ± iÃ§in de yeni gÃ¼ncellemeler oldukÃ§a faydasÄ± olacaktÄ±r. Daha fazla bilgi iÃ§in FastMM&#8217;i google&#8217;da arattÄ±rÄ±n.</li><li><strong>KodlarÄ±nÄ±zÄ± Yazarken Disiplinli Olun:</strong> KodlarÄ±nÄ±zÄ± yazarken deÄŸiÅŸken, sÄ±nÄ±f, fonksiyon isimlendirmelerinde belli bir standarta uyun. BÄ±raktÄ±ÄŸÄ±nÄ±z kod yorumlarÄ±nÄ± daha sonradan bakacak mÄ±ÅŸsÄ±nÄ±z veya baÅŸka birisi projeyi devam ettirecekmiÅŸcesine yazÄ±n. Bu ve bunun gibi kendinize kurallar belirleyerek disiplinli bir ÅŸekilde kodlarÄ±nÄ±zÄ± yazÄ±n. Bu size, daha sonradan programÄ±nÄ±zÄ± bitirdikten sonra kolay bir optimizasyon imkanÄ± saÄŸlayacak. Tekrar kodlara dÃ¶nÃ¼p baktÄ±ÄŸÄ±nÄ±zda disiplinli ve dÃ¼zenli yazÄ±lmÄ±ÅŸ bir kod gÃ¶receksiniz ve yavaÅŸ Ã§alÄ±ÅŸan veya hatalÄ± Ã§alÄ±ÅŸan kÄ±sÄ±mlarÄ± daha Ã§abuk farkedip, kodunuzu optimize edebileceksiniz.</li><li><strong>Basm Ä°le Optimizasyona Gidin:</strong> Basm yani Delphi iÃ§inde assembler kullanarak bazÄ± Ã¶nemli yerleri optimize edebilirsiniz. Ã–zellikle hÄ±zÄ±n Ã§ok Ã¶nemli olduÄŸu yerleri bu ÅŸekilde optimize edebilirsiniz. Bununla ilgili olarakÂ  daha Ã¶nceden <a
href="http://www.diyezon.com/index.php/2007/06/20/delphi-ve-c-builder-ile-assembler/" target="_blank">burada</a> bir ÅŸeyler karalamÄ±ÅŸtÄ±k.</li></ol><p
style="text-align: justify;">Tabi bunlar dÄ±ÅŸÄ±nda hÄ±zÄ± etkileyen baÅŸka faktÃ¶rlerin de olduÄŸunu unutmayÄ±n. Fakat ilk etapta bu adÄ±mlara dikkat etmeniz, programlarÄ±nÄ±zdaki Ã§alÄ±ÅŸma hÄ±zÄ±nÄ± Ã¶nemli derece artÄ±racaktÄ±r. Buradaki adÄ±mlarÄ±n Ã§oÄŸunun tek dez avantajÄ±, exe boyutunun biraz artabilmesi. Fakat bu devirde kimse exe boyutunu Ã§ok Ã¶nemsemiyor.</p><p
style="text-align: justify;">Benim aklÄ±ma 7 adÄ±m geldi fakat sizlerin de Ã¶nerileri olursa lÃ¼tfen yorum yazarak katkÄ±da bulununuz.</p><p
style="text-align: justify;"><strong>GÃ¼ncelleme: 07.03.2009:</strong> Bu maddelere ek olarak <a
href="#comment-871">buradaki yorumda</a> bulunan 3 maddeye daha gÃ¶z atmanÄ±zÄ± tavsiye ediyorum. Saadettin beye teÅŸekkÃ¼rler.</p><p
style="text-align: center;"><strong>Fatih Tolga Ata Â© 2009</strong></p> ]]></content:encoded> <wfw:commentRss>http://www.diyezon.com/7-adimda-delphi-uygulamalarini-daha-da-hizlandirin/feed/</wfw:commentRss> <slash:comments>11</slash:comments> </item> <item><title>Derleyici TasarÄ±m NotlarÄ± &#8211; 1</title><link>http://www.diyezon.com/derleyici-tasarim-notlari-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=derleyici-tasarim-notlari-1</link> <comments>http://www.diyezon.com/derleyici-tasarim-notlari-1/#comments</comments> <pubDate>Sun, 22 Feb 2009 00:45:26 +0000</pubDate> <dc:creator>Fatih Tolga Ata</dc:creator> <category><![CDATA[Derleyici TasarÄ±mÄ±]]></category><guid
isPermaLink="false">http://www.diyezon.com/?p=216</guid> <description><![CDATA[Derleyici tasarÄ±mÄ±, uzun zamandÄ±r kendimi geliÅŸtirmek iÃ§in uÄŸraÅŸtÄ±ÄŸÄ±m bir konu.Â Bu konu ile ilgili Ã§ok kitaplar ve makaleler okudum ve araÅŸtÄ±rmalar yaptÄ±m.Â Ama ne yazÄ±k ki, bu konuda kendimi ciddi manada ilerleyebilmiÅŸ olarak hissetmiyorum. Åžimdi ise bu araÅŸtÄ±rma ve notlarÄ±mÄ± burada toplamayÄ± dÃ¼ÅŸÃ¼nÃ¼yorum. BÃ¶ylece kendimi bu konuda geliÅŸtirmeyi ve bununla beraber bu notlarÄ± sizlerle paylaÅŸmayÄ± dÃ¼ÅŸÃ¼nÃ¼yorum. Bu [...]]]></description> <content:encoded><![CDATA[<p
style="text-align: justify;">Derleyici tasarÄ±mÄ±, uzun zamandÄ±r kendimi geliÅŸtirmek iÃ§in uÄŸraÅŸtÄ±ÄŸÄ±m bir konu.Â Bu konu ile ilgili Ã§ok kitaplar ve makaleler okudum ve araÅŸtÄ±rmalar yaptÄ±m.Â Ama ne yazÄ±k ki, bu konuda kendimi ciddi manada ilerleyebilmiÅŸ olarak hissetmiyorum. Åžimdi ise bu araÅŸtÄ±rma ve notlarÄ±mÄ± burada toplamayÄ± dÃ¼ÅŸÃ¼nÃ¼yorum. BÃ¶ylece kendimi bu konuda geliÅŸtirmeyi ve bununla beraber bu notlarÄ± sizlerle paylaÅŸmayÄ± dÃ¼ÅŸÃ¼nÃ¼yorum.</p><p
style="text-align: justify;">Bu yazÄ± serisi, Ã¶nceden yazdÄ±ÄŸÄ±m makaleler gibi tecrÃ¼be ve bilgiye dayalÄ± olmayacak. OkuduÄŸum kitap ve makalelerden ve denemelerimden oluÅŸacak. Bu yÃ¼zden bu makale serisinin hedeflediÄŸi kitle, sadece bu iÅŸin meraklÄ±larÄ±na hitap ediyor. Derleyici-yorumlayÄ±cÄ± yazmak isteyenlere faydalÄ± bir <strong>konu Ã¶zeti</strong> olacaÄŸÄ±nÄ± dÃ¼ÅŸÃ¼nÃ¼yorum. AyrÄ±ca bu iÅŸe yeni baÅŸlayacak olanlara veya baÅŸlamÄ±ÅŸ ama bir sebepten dolayÄ± yarÄ±m bÄ±rakmÄ±ÅŸ kimselere de bir <strong>fihrist</strong>, bir <strong>yol haritasÄ±</strong> olacaÄŸÄ±nÄ± dÃ¼ÅŸÃ¼nÃ¼yorum. Tabi bu notlarÄ± Ã§Ä±karmakla ben de kendimi bu konuda geliÅŸtirmeyi dÃ¼ÅŸÃ¼nÃ¼yorum.</p><p><span
id="more-216"></span></p><h1>BaÅŸlarken..</h1><p
style="text-align: justify; padding-left: 60px;">Ä°lk derleyici yazma merakÄ±m, bir iÅŸletim sistemi yazma merakÄ±m olduÄŸunda baÅŸladÄ± <img
src='http://www.diyezon.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> GerÃ§i iÅŸletim sistemi olarak sadece disketten boot edilebilir ve dos benzeri bir ÅŸeyler yazabildim ancak. Fakat bu gayretim bana Ã§ok ÅŸeyler kazandÄ±rdÄ±. Ã–ncelikle bilgisayar ve iÅŸletim sisteminin Ã§alÄ±ÅŸma mantÄ±ÄŸÄ±nÄ± Ã§ok iyi bir ÅŸekilde sindirdim. AyrÄ±ca assembler ve diÄŸer programlama dilleri noktasÄ±nda da Ã§ok faydasÄ± oldu. AyrÄ±ca derleyicilerin iÅŸletim sistemleri iÃ§in ne kadar <strong>Ã¶nemli</strong> ve <strong>vazgeÃ§ilmez</strong> bir ÅŸey olduÄŸunu da gÃ¶rdÃ¼m. BÃ¼tÃ¼n o kodlarÄ± assembler ile yazmak bir yana, herhangi bir hata olduÄŸunda kafayÄ± yememek bir yana. Bu tabiki ilk baÅŸlarda derleyici yazma merakÄ±ndan Ã§ok, derleyici yazma ihtiyacÄ±nÄ± doÄŸurdu.</p><p
style="text-align: justify; padding-left: 60px;">Tabi bunlar Ã§ok Ã¶ncelerde kaldÄ±. ArtÄ±k eskisi gibi iÅŸletim sistemi yazmak gibi uÃ§uk bir dÃ¼ÅŸÃ¼ncenin altÄ±na girmeyi dÃ¼ÅŸÃ¼nmÃ¼yorum. Fakat derleyici yazmak o kadar da uÃ§uk, Ã¼topik olan bir ÅŸey deÄŸil. Zira en Ã¼nlÃ¼ programalama dillerine baktÄ±ÄŸÄ±nÄ±zda hemen hemen hepsinin ilk baÅŸlarda bir veya iki kiÅŸi ile yazÄ±ldÄ±ÄŸÄ±nÄ± gÃ¶rÃ¼rsÃ¼nÃ¼z. Bu konu ile ilgili araÅŸtÄ±rma yaptÄ±kÃ§a, bu konunun anlaÅŸÄ±lmasÄ±nÄ±n Ã§ok zor olmadÄ±ÄŸÄ±nÄ± fakat teoriden pratiÄŸe, uygulamaya dÃ¶kmenin zorluÄŸunu gÃ¶rdÃ¼m. Son zamanlarda derleyici tasarÄ±m teknolojisinin geliÅŸmesiyle beraber uygulamaya dÃ¶kme iÅŸlemi de artÄ±k -eskisi gibi- Ã§ok zor deÄŸil. ZamanÄ± geldiÄŸinde bu teknolojilerden bahsetmeye Ã§alÄ±ÅŸacaÄŸÄ±m.</p><h2 style="padding-left: 30px;">Bu Makale Serisi Kime Hitap Ediyor</h2><p
style="text-align: justify; padding-left: 60px;">Ä°lk baÅŸlarda da dediÄŸim gibi Ã¶ncelikle bu iÅŸe meraklÄ± olmalÄ±sÄ±nÄ±z. Bu konu sadece derleyici veya yorumlayÄ±cÄ± yazmaktan ibaret deÄŸil tabiki. EÄŸer yabancÄ± bir dilden (mesala Ä°ngilizce&#8217;den) TÃ¼rkÃ§e Ã§eviri yapan veya tam tersi iÅŸlemi yapan bir Ã§eviri programÄ± yapmak istiyorsanÄ±z, yine bu konu iyi bilmeniz gerekiyor.</p><p
style="text-align: justify; padding-left: 60px;">Bir derleyici, yorumlayÄ±cÄ± yazabilmek iÃ§in bir programlama diline iyi hakim olmanÄ±z da gerekmektedir. Bu yÃ¼zden bu makaleyi okuyabilmeniz iÃ§in en az bir adet programlama dilini iyi bilmeniz gerekiyor. Ãœstelik nesne tabanlÄ± programlamayÄ± da bilmeniz iÅŸinizi daha da kolaylaÅŸtÄ±racaktÄ±r.</p><p
style="text-align: justify; padding-left: 60px;">AyrÄ±ca ÅŸunu da belirtmek isterim. Bu konuda TÃ¼rkÃ§e kaynak yok denecek kadar az. Bu konuda kendinizi geliÅŸtirmek istiyorsanÄ±z ilk baÅŸta Ä°ngilizce ile baÅŸlasanÄ±z fena etmezsiniz.</p><h2 style="padding-left: 30px;">Kitaplar ve Kaynaklar</h2><p
style="text-align: justify; padding-left: 60px;">Piyasada bu konu ilgili bir Ã§ok kitap mevcut. Kimi Ã§ok eski ve ÅŸu anki teknolojiye hitap etmiyor, kimisi de Ã§ok teoride kalÄ±p pratikte hiÃ§ bir kullanÄ±mÄ±ndan bahsetmiyor. Onca kitap arasÄ±ndan kendimize referans kabul edebileceÄŸimiz kitabÄ± seÃ§mek zor olabiliyor. Ben bunlardan beÄŸendiÄŸim ve gerÃ§ekten kaliteli kitaplarÄ± tavsiye edeceÄŸim. Bu kitaplar genel yorumlarda da iyi gÃ¶zle bakÄ±lan ve gÃ¼nÃ¼mÃ¼z derleyici teknolojilerine de uygun kitaplardÄ±r.</p><p
style="padding-left: 60px;">Benim tavsiye edebileceÄŸim kitaplar ÅŸunlar:</p><p
style="text-align: justify; padding-left: 60px;"><strong>Compilers, Principles, Techniques and Tools; 2nd Edition:</strong> Bu kitap, derleyici tasarÄ±mÄ±nÄ±n temel ve vazgeÃ§ilmez kitabÄ± olarak kabul edilir. Derleyici tasarÄ±mcÄ±larÄ± arasÄ±nda ilk baskÄ±sÄ±nÄ±n kapaÄŸÄ±ndaki ejder figÃ¼rÃ¼nden dolayÄ± &#8220;Dragon Book&#8221; ismiyle anÄ±lmaktadÄ±r. KitabÄ±n ilk baskÄ±sÄ± yanÄ±lmÄ±yorsam 1986 yÄ±lÄ±nda yayÄ±nlanmÄ±ÅŸ. Fakat benim tavsiye edeceÄŸim 2. baskÄ±sÄ±dÄ±r. 2. baskÄ±sÄ± 2006&#8242;da Ã§Ä±ktÄ± ve deÄŸiÅŸen bir Ã§ok derleyici teknolojisini barÄ±ndÄ±rmaktadÄ±r. Ä°yi bir baÅŸlangÄ±Ã§ yapmak isteyen ve yanÄ± baÅŸÄ±nda referans kitap olarak bulundurmak isteyenlere tavsiye ediyorum.</p><p
style="text-align: justify; padding-left: 60px;"><strong>Engineering a Compiler (<em>Cooper, Torczon</em>):</strong>Â Bu kitabÄ± Ã§ok aramama raÄŸman ancak ebay Ã¼zerinde bulabildim. SÄ±fÄ±r almak isteyenler iÃ§in amazonda da mevcut. Ebook olarak bulmayÄ± niyetlenenlere sÃ¶yleyeceÄŸim ÅŸey ÅŸu ki, bu kitabÄ±n internet Ã¼zerindeki ebooklarÄ± eksik. Daha doÄŸrusu draft, yani yazarÄ±n kitap Ã§Ä±kmadan Ã§ok Ã¶nceki taslak metinlerinden oluÅŸuyor. Åžu ana kadar incelediÄŸim kitaplar arasÄ±nda iÅŸe yarar, teori ve pratik bilgisi iyi olan ve yeni derleyici teknolojilerine hitap eden nadir kitaplardan birisi.</p><p
style="text-align: justify; padding-left: 60px;"><strong>The Definitive ANTLR Reference:</strong>Â Ä°leride bahsedeceÄŸim derleyici derleyicilerinden birisi olan ANTLR ile ilgili yazÄ±lmÄ±ÅŸ gÃ¼zel bir kitap. ANTLR derleyici derleyicisini tasarlayan ve yazan Terence Parr tarafÄ±ndan yazÄ±lmÄ±ÅŸ olan kitapta, sadece ANTLR ile ilgili bilgi bulunmamakta. Bu kitapta derleyici tasarÄ±mÄ±nÄ±n temel bilgileri yanÄ±nda gramer oluÅŸturma, lexer, parser Ã§alÄ±ÅŸma mantÄ±klarÄ± ve LL Ã§akÄ±ÅŸmalarÄ± gibi bir Ã§ok konuda bilgi de bulunmakta. Ã–nceki iki kitap, her ne kadar pratikte kullanÄ±labilecek bilgiler iÃ§erse de genelde teoriyi hedefleyen kitaplardÄ±r. Fakat bu kitap, Ã¶ÄŸrendiÄŸimiz teoriyi uygulumaya nasÄ±l dÃ¶kebilceÄŸimizi ayrÄ±ntÄ±sÄ± ile anlatmakta.</p><p
style="text-align: justify; padding-left: 60px;">Derleyici-yorumlayÄ±cÄ± yazmak isteyen herkese bu Ã¼Ã§ kitabÄ± ÅŸiddetle tavsie ediyorum. Bunlar dÄ±ÅŸÄ±nda yardÄ±mcÄ± olabilecek ÅŸu kitaplara da gÃ¶z atabilirsiniz.Â</p><div
style="padding-left: 60px;"><ul><li>Advanced Programming Language Design (Raphael A. Finkel)</li><li>Build Your Own Net Language And Compiler (Edward G. Nigles)</li><li>Let&#8217;s Build a Compiler (Jack W. Crenshaw) (ÅŸu linkte bedava daÄŸÄ±tÄ±lmaktadÄ±r:Â http://compilers.iecc.com/crenshaw/)</li><li>Building An Optimizing Compiler (Bob Morgan)</li><li>Compiler and Compiler Generators (P.D. Terry)</li><li>Algorithms for Compiler Design (O.G. Kakde)</li><li>Modern Compiler Implementation in Java (Andrew W. Appel)</li><li>Compiler Construction (Kneeth C. Louden)</li></ul></div><p
style="text-align: justify; padding-left: 60px;">Bu kitaplarla beraber bir sorununuz olduÄŸunda, internet Ã¼zerinde ANTLR ve Coco/R mail listeleri sizlere yardÄ±mcÄ± olacaktÄ±r.</p><p
style="text-align: justify; padding-left: 60px;">AyrÄ±ca sourcefoge.net gibi bir Ã§ok sitede bulabileceÄŸiniz aÃ§Ä±k kaynak kodlu derleyici projeleri bulunmaktadÄ±r. Ã–zellikle Tiny C benzeri bir Ã§ok aÃ§Ä±k kaynak kodlu ve kÃ¼Ã§Ã¼k (yani incelenebilir) derleyicilere ulaÅŸabilirsiniz. Gcc, freepascal gibi bÃ¼yÃ¼k projeleri de inceleyebilirsiniz. Fakat bu projeler Ã§ok bÃ¼yÃ¼k olduklarÄ±ndan pek Ã¶ÄŸretme/Ã¶ÄŸrenme amaÃ§lÄ± deÄŸiller. Bunun yerine daha Ã§ok kÃ¼Ã§Ã¼k ve deneysel projeleri bulup incelemekte yarar var.</p><p
style="text-align: justify; padding-left: 60px;">Ben yeri geldikÃ§e bu tarz projeleri bulup sizlerle paylaÅŸacaÄŸÄ±m. AyrÄ±ca yeni Ã§Ä±kmÄ±ÅŸ olan veya benim yeni keÅŸfettiÄŸim gÃ¼zel kitaplarÄ± da burada yeri geldikÃ§e tanÄ±tmaya Ã§alÄ±ÅŸacaÄŸÄ±m.</p><p
style="text-align: justify; padding-left: 60px;">Bir sonraki bÃ¶lÃ¼mde derleyiciler hakkÄ±nda temel teorik bilgiler bulacaksÄ±nÄ±z. Bir sonraki bÃ¶lÃ¼mde anlamadÄ±ÄŸÄ±nÄ±z yerler olursa burada verdiÄŸim kitap ve kaynaklardan istifade edererek araÅŸtÄ±rÄ±rsÄ±nÄ±z. Ã‡Ã¼nkÃ¼ bunlar temel konulardÄ±r ve sonrasÄ±nda gelecek olan bÃ¶lÃ¼mler bu temel bilgiler Ã¼zerine inÅŸa edilecektir.</p><h1>BÃ¶lÃ¼m 1: Derleyiciler ve Ã‡alÄ±ÅŸma MantÄ±ÄŸÄ±</h1><p
style="text-align: justify; padding-left: 60px;">Derleyici tasarÄ±mÄ±, bilgisayar biliminde Ã¶nemli bir sahayÄ± oluÅŸturmaktadÄ±r. En basit olarak bir derleyici, bÃ¼yÃ¼k bir bilgisayar programÄ±dÄ±r. Bir derleyici, kaynak kodu alÄ±r ve belli bir bilgisayar mimarisine uygun Ã§alÄ±ÅŸtÄ±rÄ±labilir bir hedefe Ã§evirir. Bu Ã§evirimin bir parÃ§asÄ± da girilen kaynak kodun imla analizini yani syntax analizini yapmaktÄ±r. Bu imla analizi sonucunda, kaynak kodlarda hata tespiti yapÄ±lÄ±r ve kaynak kodun derleyici iÃ§indeki karÅŸÄ±lÄ±klarÄ±na Ã§evrilir. Derleyeci, daha sonra, bu Ã§evrilmiÅŸ olan kaynaklara bir mÃ¢nÃ¢, anlam yÃ¼kler. Bu anlam yÃ¼klemesi sonucunda, derleyici anlam hatalarÄ±nÄ± araÅŸtÄ±rÄ±r. Bu iÅŸlemden sonra da kaynak kodun derleyicide ifade ettiÄŸi anlama gÃ¶re hedeflenen Ã§Ä±ktÄ± Ã¼retilir.Â Tabi bu aÃ§Ä±klama Ã§ok yÃ¼zeysel bir aÃ§Ä±klama ve adeta bu bÃ¶lÃ¼mde gÃ¶receklerimizin bir Ã¶zeti hÃ¼kmÃ¼nde oldu.</p><p
style="text-align: justify; padding-left: 60px;">Derleyici tasarÄ±mÄ±, bir mÃ¼hendislik Ã§alÄ±ÅŸmasÄ±dÄ±r ayrÄ±ca. Derleyici yazarÄ±, bu yolda kendisine bol alternatifi olan, masrafÄ±, avantajlarÄ± ve zorluÄŸu belirgin olan bir tasarÄ±m ortamÄ± oluÅŸturmak zorundadÄ±r. Her bir karar, oluÅŸturulacak olan derleyiciyi etkileyecektir. OluÅŸturulacak olan Ã¼rÃ¼nÃ¼n kalitesi bu alÄ±nan kararlara baÄŸlÄ±dÄ±r.</p><p
style="text-align: justify; padding-left: 60px;">Derleyici tasarÄ±mÄ±, Ã§ok eski olmamasÄ±na raÄŸmen, tatmin edici seviyelere kadar geliÅŸmiÅŸ bir konudur. Bu konuda bir Ã§ok baÅŸarÄ±lara imza atÄ±lmÄ±ÅŸtÄ±r. Piyasada olan bir Ã§ok derleyici ve binlerce Ã§eÅŸit programalama dili ile beraber, bu konudaki bilgiler kullanÄ±larak geliÅŸtirilmiÅŸ bir Ã§ok program, bunun ispatÄ±dÄ±r. Bir problemi Ã§Ã¶zmek iÃ§in bir Ã§ok yÃ¶ntem geliÅŸtirilmiÅŸtir. Ben burada en gÃ¼ncel ve popÃ¼ler tekniklerden bahsetmeye Ã§alÄ±ÅŸacaÄŸÄ±m. Ama bilinki, bahsedeceÄŸimiz her bir konu ve teknik iÃ§in alternatifler mevcuttur. Bu alternatifleri araÅŸtÄ±rmak size kalmÄ±ÅŸ.</p><h2 style="padding-left: 30px;">Derleme Ä°ÅŸlemine Genel BakÄ±ÅŸ</h2><p
style="text-align: justify; padding-left: 60px;">Bir program Ã§alÄ±ÅŸtÄ±rÄ±labilir olmadan Ã¶nce, bir Ã§ok Ã§evirim iÅŸlemlerine tabi tutularak hedef Ã§alÄ±ÅŸtÄ±rÄ±labilir kodlar oluÅŸturulurlar. Bu Ã§evirim iÅŸlemini yapan programÄ±n Ã¶zel adÄ±na <strong>derleyici</strong> (<em>compiler</em>) diyoruz. Derleyici, kendisinin anlayacaÄŸÄ± bir dilde kaynak kodlarÄ±nÄ± alÄ±r ve Ã§Ä±kÄ±ÅŸta Ã§alÄ±ÅŸtÄ±rÄ±labilir kodlar Ã¼retir. Bu Ã§alÄ±ÅŸtÄ±rÄ±labilir kodlar Windows&#8217;da exe, dll, Linux&#8217;de elf, so gibi dosyalar olabilceÄŸi gibi, .net, java gibi sanal makinalar iÃ§in Ã§alÄ±ÅŸtÄ±rÄ±labilir kodlar da Ã¼retebilir.</p><p
style="text-align: justify; padding-left: 60px;">AyrÄ±ca Ã§alÄ±ÅŸtÄ±rÄ±labilir kodlar, direk olarak iÅŸleme de tabi tutulabilirler. Yani javascript, vbscript gibi direk olarak derleme anÄ±nda Ã§alÄ±ÅŸan derleyiciler de mevcuttur. Bu tip derleyicilerin Ã¶zel adÄ±na ise <strong>yorumlayÄ±cÄ±</strong> (<em>interpreter</em>) denilir. Her ne kadar bazÄ± eski kaynaklarda yorumlayÄ±cÄ±lar ve derleyiciler iki farklÄ± ÅŸeylermiÅŸ gibi gÃ¶sterilse de Ã§alÄ±ÅŸma mantÄ±klarÄ± aynÄ± olduÄŸu iÃ§in hepsine genel olarak derleyici demeyi uygun buluyorum. Ã‡Ã¼nkÃ¼ derleme iÅŸleminde, ileride ayrÄ±ntÄ±sÄ± ile gÃ¶receÄŸimiz gibi, ilk safha yorumlama, ikinci safha ise kod Ã¼retmedir. YorumlayÄ±cÄ±larÄ±n tek farkÄ±, kod Ã¼retme safhasÄ± bulunmamasÄ±dÄ±r.</p><p
style="text-align: justify; padding-left: 60px;">AyrÄ±ca yorumlayÄ±cÄ± kodlarÄ±, Ã§alÄ±ÅŸabilmek iÃ§in bir yorumlayÄ±cÄ±ya ihtiyaÃ§ duyarlar. Mesela php kodlarÄ± php derleyicisine, basic kodlarÄ± basic derleyicisine, javascript kodlarÄ± ecmascript destekli bir browser&#8217;a ihtiyaÃ§ duyarlar. Bu kodlar, yorumlayÄ±cÄ± olmadan Ã§alÄ±ÅŸtÄ±rÄ±lamazlar. Fakat C++, Delphi gibi derleyicilerin Ã¼rettiÄŸi kodlarÄ±, direk olarak iÅŸletim sistemi Ã¼zerinden iÅŸlemci Ã§alÄ±ÅŸtÄ±rmaktadÄ±r, daha sonradan derleyiciye ihtiyaÃ§larÄ± yoktur.</p><p
style="text-align: justify; padding-left: 60px;">Bir de gÃ¼nÃ¼mÃ¼z teknolojisinde yorumlayÄ±cÄ± olan ama temelde derleyiciler gibi kod Ã¼retebilen derleyiciler de mevcuttur. Mesela php derleyicisi, yorumlayÄ±cÄ± gibi ayrÄ± bir dosyaya iÅŸletim sistemine uygun bir kod Ã¼retmeden, hemen Ã§alÄ±ÅŸmaya baÅŸlar. Fakat yorumlayÄ±cÄ±lardan farklÄ± olarak &#8220;kod Ã¼retir&#8221;. Bu kod tabiki ayÄ±r bir dosya deÄŸil, IIS, Apache gibi server&#8217;lara uygun yapÄ±da opcode&#8217;lardÄ±r.</p><p
style="text-align: justify; padding-left: 60px;">GÃ¼nÃ¼mÃ¼zde derleme iÅŸlemi yapan bir programÄ±, yorumlayÄ±cÄ±, derleyici olarak kesin bir ÅŸekilde ayÄ±rmak zorlaÅŸmÄ±ÅŸtÄ±r. Bunun yerine hepsine derleyici demek ve derleme iÅŸlemindeki ilk bÃ¶lÃ¼me yorumlayÄ±cÄ± demek daha doÄŸru olacaktÄ±r. Ve bu mantÄ±ÄŸÄ±n kavram karmaÅŸasÄ±nÄ± da Ã¶nleyeceÄŸini dÃ¼ÅŸÃ¼nÃ¼yorum. Ve herhangi bir yorumlayÄ±cÄ±ya derleyici demeyi de yanlÄ±ÅŸ bulmuyorum. (Php yorumlayÄ±cÄ±sÄ± yerine, php derleyicisi demek bana daha uygun geliyor&#8230;)</p><p
style="text-align: justify; padding-left: 60px;">Peki, kaynak kodumuz, derleyici ile tanÄ±ÅŸtÄ±ktan sonra hangi aÅŸamalardan ve safhalardan geÃ§iyor? Bu konuyu ayrÄ±ntÄ±sÄ± ile ilerleyen bÃ¶lÃ¼mlerde gÃ¶receÄŸiz. Burada Ã¶zet mahiyetinde ÅŸÃ¶yle bahsedebiliriz:</p><div
id="attachment_250" class="wp-caption aligncenter" style="width: 519px"><img
class="size-full wp-image-250" title="Derleyici Ä°ÅŸleyiÅŸ DiagramÄ±" src="http://www.diyezon.com/wp-content/uploads/post216_fig1.png" alt="Derleyici Ä°ÅŸleyiÅŸ DiagramÄ±" width="509" height="302" /><p
class="wp-caption-text">Derleyici Ä°ÅŸleyiÅŸ DiagramÄ±</p></div><p
style="text-align: justify; padding-left: 60px;">Genel manada bu ÅŸekilde olsa da hem arka planda, hemde gÃ¶rÃ¼ntÃ¼de bir Ã§ok safha deÄŸiÅŸebilmektedir.</p><p
style="text-align: justify; padding-left: 60px;">Kaynak kod derleyicimize geldiÄŸi vakit, ilk olarak, kaynak kodun harfleri teker teker iÅŸlenir ve tanÄ±mlanarak <strong>token</strong> dediÄŸimiz nesnelere dÃ¶nÃ¼ÅŸtÃ¼rÃ¼lÃ¼rler. Bu iÅŸlemi gerÃ§ekleÅŸtiren parÃ§aya <strong>Lexer</strong> denilir. Lexer&#8217;Ä±n gÃ¶revi, imla (syntax) analizi yapÄ±p sonuÃ§ olarak bir <strong>token</strong> listesi oluÅŸturmaktÄ±r. Bu imla analizi sÄ±rasÄ±nda kaynak kodda hatalar da bulunabilir. Bu hatalar Lexer tarafÄ±ndan tespit edilir ve <strong>imla hatasÄ±</strong> (<em>syntax error</em>) olarak bildirilir. Lexer, kaynak kodun ifade ettiÄŸi, edeceÄŸi anlam ile uÄŸraÅŸmaz. Hangi token&#8217;nÄ±n hangisinden sonra geldiÄŸi ile ilgilenmez.</p><p
style="text-align: justify; padding-left: 60px;">Mesela aÅŸaÄŸÄ±daki karakter katarÄ±na bakalÄ±m.</p><p
style="text-align: justify; padding-left: 60px;"><img
class="aligncenter size-full wp-image-249" title="post216_fig2" src="http://www.diyezon.com/wp-content/uploads/post216_fig2.png" alt="post216_fig2" width="230" height="53" /></p><p
style="text-align: justify; padding-left: 60px;">Lexer, bu karakter katarÄ±ndaki her bir karakteri ayrÄ±ÅŸtÄ±rÄ±r. &#8220;width&#8221; kelimesini bir token, &#8220;:=&#8221; atama operatÃ¶rÃ¼nÃ¼ bir token, 2 sayÄ±sÄ±nÄ± bir token ve &#8220;;&#8221; iÅŸaretini bir baÅŸka token olarak belirler. EÄŸer gramere gÃ¶re bu karakter katarÄ±nda hata mevcut deÄŸilse token listesini Ã¼retir. Burada ayrÄ±ca her bir boÅŸluk da, kimi lexer&#8217;lar tarafÄ±ndan, birer token olarak kabul edilmektedir. Ä°leride ayrÄ±ntÄ±sÄ±nÄ± gÃ¶receÄŸimiz token&#8217;Ä± Delphi&#8217;deki bir record veya C++&#8217;daki bir struct yapÄ±sÄ±na benzetebilirsiniz. Bu record ya da struct iÃ§inde, token&#8217;nÄ±n tÃ¼rÃ¼, bulunduÄŸu pozisyon gibi deÄŸerler bulunur.</p><p
style="text-align: justify; padding-left: 60px;">Lexer, token listesini oluÅŸturduktan sonra iÅŸlemini tamamlamÄ±ÅŸtÄ±r. ArtÄ±k bu token listesini, <strong>Parser</strong> dediÄŸimiz baÅŸka bir derleyici parÃ§asÄ±na iletir.</p><p
style="text-align: justify; padding-left: 60px;">Parser, bu token listesini alÄ±r ve bir aÄŸaÃ§ yapÄ±sÄ± Ã¼retir. Bu oluÅŸturulan aÄŸaca, <strong>Parse AÄŸacÄ±</strong> denilir. Token listesinden oluÅŸturulmuÅŸ olan parse aÄŸacÄ±, yine tokenlardan oluÅŸmuÅŸ bir yapÄ±dÄ±r ve derleyicinin tanÄ±dÄ±ÄŸÄ± gramere gÃ¶re oluÅŸturulur. Parser eÄŸer aÄŸacÄ± oluÅŸtururken gramere uygun olmayan bir token ile karÅŸÄ±laÅŸÄ±rsa bunu hata olarak bildirir. ParserÄ±n Ã¼rettiÄŸi bu hataya &#8220;<strong>Gramer HatasÄ±</strong>&#8221; yada &#8220;<strong>Parse HatasÄ±</strong>&#8221; (<em>Parse Error</em>) denilir.</p><p
style="text-align: justify; padding-left: 60px;">Parser, token iÃ§inde bulunan ve tokenÄ±n ifade ettiÄŸi text ile uÄŸraÅŸmaz. TokenÄ±n karakter katarÄ±nda hangi pozisyonda bulunduÄŸu ile ilgilenmez. AyrÄ±ca parser, lexer gibi, tokenÄ±n ifade ettiÄŸi anlam ile uÄŸraÅŸmaz. Parser sadece token listesinin diziliÅŸine gÃ¶re gramere uygunluÄŸu kontrol eder. Bunun sonucunda da bu token listesinden oluÅŸan bir parse aÄŸacÄ± Ã¼retir.</p><p
style="text-align: justify; padding-left: 60px;">Misal olarak aÅŸaÄŸÄ±daki karakter katarÄ±ndan, Lexer ve Parser&#8217;Ä±n Ã¼rettiÄŸi Ã§Ä±ktÄ±lara bakalÄ±m:</p><p
style="text-align: justify; padding-left: 60px;">Â</p><div
id="attachment_252" class="wp-caption aligncenter" style="width: 317px"><img
class="size-full wp-image-252" title="Lexer ve Parser Ä°ÅŸleyiÅŸi" src="http://www.diyezon.com/wp-content/uploads/post216_fig3.png" alt="Lexer ve Parser Ä°ÅŸleyiÅŸi" width="307" height="459" /><p
class="wp-caption-text">Lexer ve Parser Ä°ÅŸleyiÅŸi</p></div><p
style="text-align: justify; padding-left: 60px;">Bu aÄŸacÄ±n oluÅŸturulmasÄ±nÄ±n amacÄ±na daha sonra deÄŸineceÄŸiz.</p><p
style="text-align: justify; padding-left: 60px;">Parse aÄŸacÄ± oluÅŸtuktan sonra bu aÄŸaÃ§, <strong>Semantik Analiz&#8217;</strong>e (<em>Semantic Analysis</em>) tabi tutulur. AÄŸacÄ±n her bir yapraÄŸÄ±nda bulunan tokenlar, bu aÅŸamada derleyici iÃ§in bir mÃ¢nÃ¢ ifade etmeye baÅŸlarlar. Yani artÄ±k integer olan bir token, derleyici tarafÄ±ndan integer, deÄŸiÅŸken olan token ise deÄŸiÅŸken olarak anlam verilir. Bunun sonucunda ise, anlam olarak belli hatalar oluÅŸabilir. Bu aÅŸamada oluÅŸabilecek hatalara <strong>Semantik Hatalar</strong> (<em>Semantic Errors</em>) denilir. Mesela integer olan bir deÄŸiÅŸken, string olan bir deÄŸiÅŸkene direk olarak eÅŸitlenemez! Tabi bu Ã¶rnek programlama dillerine gÃ¶re farklÄ±lÄ±k da gÃ¶sterebilir. Fakat genel manada integer bir deÄŸeri string bir deÄŸere direk olarak eÅŸitleyemezsiniz. Ã‡Ã¼nkÃ¼Â bunlarÄ±nÂ token tipleri farklÄ±dÄ±r. Bu tarzdaki, yani anlam bakÄ±mÄ±ndan yanlÄ±ÅŸ olan iÅŸlemler semantik hatalarÄ± oluÅŸtururlar.</p><p
style="text-align: justify; padding-left: 60px;">Semantik analiz sonucunda herhangi bir hata oluÅŸmamÄ±ÅŸ ise parse aÄŸacÄ± yardÄ±mÄ± ile <strong>intermediate code</strong>Â ya da <strong>intermediate representation</strong> dediÄŸimiz ara bir kod oluÅŸturulur. Tabi bu safha her derleyicide bulunmayabilir. Bu ara kod oluÅŸturulduktan sonra kodlar optimize edilir ve tekrar son Ã§Ä±ktÄ± iÃ§in kod Ã¼retilir. BazÄ± derleyiciler ara kod oluÅŸturmadan direk olarak kod oluÅŸturabilmektedir.</p><p
style="text-align: justify; padding-left: 60px;">Bu iÅŸlemlerden bizi en Ã§ok zorlayan kÄ±sÄ±m lexer ve parser kÄ±sÄ±mlarÄ±dÄ±r. Ã‡Ã¼nkÃ¼ bu parÃ§alar, programlama dilinin gramerini ifade eden, tanÄ±mlanmasÄ±nda hata kabul etmeyen, hamaliyesi Ã§ok olan parÃ§alardÄ±r. Bu zorluklardan dolayÄ± bir Ã§ok &#8220;derleyici derleyicisi&#8221; denilen yardÄ±mcÄ± programlar geliÅŸtirilmiÅŸtir.Â Her bÃ¼yÃ¼k derleyicide bu derleyici derleyicisi kullanÄ±lmaktadÄ±r.Â Bunu daha sonra ayrÄ±ntÄ±sÄ± ile gÃ¶receÄŸiz.</p><p
style="text-align: justify; padding-left: 60px;">Burada bahsettiÄŸimiz tabirler yabancÄ± gelse de, ileride bunlarÄ± daha iyi ve ayrÄ±ntÄ±sÄ± ile bahsedeceÄŸiz. Ama genel olarak &#8220;Derleyici TasarÄ±m NotlarÄ±&#8221; baÅŸlÄ±klÄ± bu yazÄ± serimiz bunlardan bahsedecektir. Burada bir nevi, anlatacaklarÄ±mÄ±zÄ± Ã¶zetlemiÅŸ olduk. Fakat ayrÄ±ntÄ±da gizli, Ã§ok farklÄ± teknikler ve yÃ¶ntemler mevcut. Bunlara yeri geldikÃ§e bahsedeceÄŸiz.</p><p
style="text-align: justify; padding-left: 60px;">Â</p><p
style="text-align: justify; padding-left: 60px;">________________________________</p><p
style="text-align: justify;">Birinci bÃ¶lÃ¼m henÃ¼z bitmiÅŸ deÄŸil. DevamÄ±nÄ± bir baÅŸka zamana atÄ±yorum.Â</p><p
style="text-align: justify;">Kolay gelsin.</p><p
style="text-align: center;"><strong>Fatih Tolga Ata Â© 2009</strong></p> ]]></content:encoded> <wfw:commentRss>http://www.diyezon.com/derleyici-tasarim-notlari-1/feed/</wfw:commentRss> <slash:comments>26</slash:comments> </item> <item><title>C / C++ &#8216;dan Delphi&#8217;ye Kod Ã‡evirme Klavuzu (1)</title><link>http://www.diyezon.com/c-den-delphiye-kod-cevirme-klavuzu-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=c-den-delphiye-kod-cevirme-klavuzu-1</link> <comments>http://www.diyezon.com/c-den-delphiye-kod-cevirme-klavuzu-1/#comments</comments> <pubDate>Thu, 19 Feb 2009 02:30:30 +0000</pubDate> <dc:creator>Fatih Tolga Ata</dc:creator> <category><![CDATA[Delphi]]></category> <category><![CDATA[C]]></category> <category><![CDATA[header]]></category> <category><![CDATA[kod Ã§evirme]]></category><guid
isPermaLink="false">http://www.diyezon.com/?p=57</guid> <description><![CDATA[Ã–zellikle iÅŸe yarar bir kÃ¼tÃ¼phane bulduÄŸunuz zaman eÄŸer yoksa hemen Delphi sÃ¼rÃ¼mlerini araÅŸtÄ±rÄ±rÄ±z. Ã‡oÄŸu zaman &#8220;Delphi port&#8221; ismiyle, kÃ¼tÃ¼phanelerin Delphi versiyonlarÄ±na eriÅŸebiliriz. EÄŸer Delphi versiyonlarÄ±nÄ± bulamazsak, iÅŸ baÅŸa dÃ¼ÅŸmÃ¼ÅŸ demektir.Â  KÃ¼tÃ¼phaneler bir Ã§ok dilde olabilirler. Fakat genel manada en Ã§ok C++ veya C kodlarÄ±nÄ±n adaptasyonu ve Ã§evrilmesi programcÄ±larÄ± zorlayabilmektedir. Bu yazÄ±mÄ±zda C / C++ ve [...]]]></description> <content:encoded><![CDATA[<p
style="text-align: justify;">Ã–zellikle iÅŸe yarar bir kÃ¼tÃ¼phane bulduÄŸunuz zaman eÄŸer yoksa hemen Delphi sÃ¼rÃ¼mlerini araÅŸtÄ±rÄ±rÄ±z. Ã‡oÄŸu zaman &#8220;Delphi port&#8221; ismiyle, kÃ¼tÃ¼phanelerin Delphi versiyonlarÄ±na eriÅŸebiliriz. EÄŸer Delphi versiyonlarÄ±nÄ± bulamazsak, iÅŸ baÅŸa dÃ¼ÅŸmÃ¼ÅŸ demektir.Â  KÃ¼tÃ¼phaneler bir Ã§ok dilde olabilirler. Fakat genel manada en Ã§ok C++ veya C kodlarÄ±nÄ±n adaptasyonu ve Ã§evrilmesi programcÄ±larÄ± zorlayabilmektedir.</p><p
style="text-align: justify;">Bu yazÄ±mÄ±zda C / C++ ve Delphi gramer bilgisi vermek yerine, daha Ã§ok C / C++ kodlarÄ±nÄ± en doÄŸru ÅŸekilde Delphi&#8217;ye nasÄ±l adapte edebileceÄŸimizi gÃ¶receÄŸiz. YapacaÄŸÄ±mÄ±z iÅŸlem sadece bire bir kod Ã§evirisi olmayacak. Yeri geldiÄŸinde hiÃ§ bir kod Ã§evirmeden sadece orjinal kÃ¼tÃ¼phaneyi Delphi programÄ±mÄ±zÄ±n iÃ§ine gÃ¶mebileceÄŸiz.</p><p
style="text-align: justify;">EÄŸer siz de, ister derlenmiÅŸ olsun, ister aÃ§Ä±k kaynak kodlu olsun, bir C / C++ kÃ¼tÃ¼phanesini Delphi&#8217;ye nasÄ±l Ã§evirebileceÄŸimizi merak ediyorsanÄ±z buyurun beraber yazÄ±mÄ±za giriÅŸ yapalÄ±m.</p><p><span
id="more-57"></span></p><h1>GiriÅŸ</h1><p
style="text-align: justify;">C / C++ &#8216;dan Delphi&#8217;ye kod Ã§evirme derken ilk akla gelen, binlerce satÄ±rlÄ±k C kodlarÄ±nÄ± teker teker uÄŸraÅŸÄ±p Delphi olarak yazmak gelecektir. Halbuki bu en son tercihimiz olmasÄ± gerekmektedir. Ä°lerleyen bÃ¶lÃ¼mlerde de gÃ¶receÄŸimiz gibi, Delphi derleyicisinin hÃ¼nerli parmaklarÄ± bizi bir Ã§ok dertten kurtarmaktadÄ±r. Yine de bÃ¼tÃ¼n kodlarÄ± baÅŸtan Ã§evirmek gibi bir derdin altÄ±na girmek isterseniz bu makale size bir baÅŸlangÄ±Ã§ noktasÄ± olacaktÄ±r.</p><p
style="text-align: justify;">Hemen kodlara dalmak gerÃ§ekten gerekli mi? Kesinlikle gerekli deÄŸil. Ã‡Ã¼nkÃ¼ bizim uÄŸraÅŸtÄ±ÄŸÄ±mÄ±z ÅŸey, Ã¶nceden birileri tarafÄ±ndan yapÄ±lÄ±p internet Ã¼zerinde daÄŸÄ±tÄ±lÄ±yor olabilir. Bu yÃ¼zden ilk yapacaÄŸÄ±mÄ±z iÅŸlem bir &#8220;Delphi port&#8221; bulmamÄ±z gerekmetedir.</p><p
style="text-align: justify;">Mesela ÅŸuanda en hÄ±zlÄ± ve en stabil xml kÃ¼tÃ¼phanesi kabul edilen libxml2 kÃ¼tÃ¼phanesini kullanmak istediÄŸimizde, hemen kodlarÄ± Ã§evirmeye kalkmak yerine bir Delphi port bulmamÄ±z en akÄ±llÄ±ca iÅŸlem olacaktÄ±r. Ki bu kÃ¼tÃ¼phanenin baÅŸlÄ±k dosyalarÄ± zaten sourceforge Ã¼zerinde daÄŸÄ±tÄ±lmaktadÄ±r.</p><p
style="text-align: justify;">Bu makalede, C objelerinin kullanÄ±mÄ±, C veri tiplerinin Delphi&#8217;deki karÅŸÄ±lÄ±klarÄ±, C baÅŸlÄ±k (header .h) dosyalarÄ±nÄ±n Delphi&#8217;ye Ã§evrilmesi gibi bir Ã§ok konu bulacaksÄ±nÄ±z. Bu bilgiler ile istediÄŸiniz bir C kÃ¼tÃ¼phanesini korkmadan Delphi&#8217;ye adapte edebilirsiniz.</p><p
style="text-align: justify;">Bu makalede Ã§ok fazla C / C++ bilgisi gerekli mi? Gerekli olsa bu makaleye ihtiyaÃ§ duymazdÄ±nÄ±z. Fakat Ã§okÂ  az da olsa C / C++ gramerine aÅŸinalÄ±ÄŸÄ±nÄ±z olmak zorunda. En basit olarak bir bir fonksiyon nasÄ±l tanÄ±mlanÄ±r, bir deÄŸiÅŸken nasÄ±l tanÄ±mlanÄ±r, bir pointer nasÄ±l atanÄ±r, bunlarÄ± bilmeniz gerekmektedir.</p><h1>Fonksiyon Ã‡aÄŸÄ±rÄ±m MekanizmalarÄ±</h1><p
style="text-align: justify;">Bir Ã§inli ile anlaÅŸabilmek iÃ§in bir tercÃ¼man tutmanÄ±z gerekti. Fakat Ã§ok aramanÄ±za raÄŸmen Ã§inli bir tercÃ¼man bulamadÄ±nÄ±z. Bunun yerine bir birine benziyor diye kalkÄ±p, japonca bir tercÃ¼man tuttunuz. Ã‡inli olan birisi ile ne kadar anlaÅŸabilirsiniz. Her ne kadar bize &#8220;benzer&#8221; gibi gÃ¶zÃ¼kse de iki dil bir birinden farklÄ± dildir. Bu Ã¶rneÄŸi ÅŸimdi gÃ¶receÄŸimiz konuya hazÄ±rlamak iÃ§in verdim. Bu misalden hakikate ÅŸu ÅŸekilde geÃ§ebiliriz. DerlenmiÅŸ olan her bir kÃ¼tÃ¼phanedeki fonksiyonlar belli bir dili konuÅŸmaktadÄ±rlar. Bu konuÅŸtuklarÄ± diller gÃ¶rÃ¼nÃ¼ÅŸte bir birlerine benzeseler de, ayrÄ±ntÄ±da bir birlerinden farklÄ±dÄ±rlar. Bu konuÅŸulan dillere fonksiyon mekanizmalarÄ± ya da ingilizce terim olarak &#8220;calling conventions&#8221; denilmektedir. EÄŸer kullanacaÄŸÄ±nÄ±z fonksiyon farklÄ± bir dili kullanÄ±yor ve siz de fonksiyonu farklÄ± bir dil ile Ã§aÄŸÄ±rÄ±yorsanÄ±z muhtemel hatalar ile karÅŸÄ±laÅŸacaksÄ±nÄ±z. Bu yÃ¼zden ilk Ã¶ÄŸreneceÄŸimiz konu bu olmalÄ±dÄ±r.</p><p
style="text-align: justify;">Direk olarak Ã§aÄŸÄ±rÄ±m mekanizmalarÄ±nÄ±n delphi karÅŸÄ±lÄ±klarÄ±nÄ± vermek yerine az da olsa bir kaÃ§ Ã¶zelliklerinden bahsetmek istiyorum. Ã‡Ã¼nkÃ¼ hangi Ã§aÄŸÄ±rÄ±mÄ± nerede ne iÃ§in kullanacaÄŸÄ±mÄ±zÄ± bilmemiz ÅŸarttÄ±r.</p><p
style="text-align: justify;">Åžu an literatÃ¼rde en Ã§ok kullanÄ±lan 4 Ã§eÅŸit fonksiyon Ã§aÄŸÄ±rÄ±m mekanizmasÄ± vardÄ±r. BunlarÄ±n ne olduÄŸunu ayrÄ±ntÄ±sÄ± ile anlatan <a
href="http://www.diyezon.com/index.php/2007/06/23/fonksiyon-cagirim-mekanizmalari/" target="_blank">buradaki</a> makalemize gÃ¶z atabilirsiniz. Hatta okumadÄ± iseniz bir gÃ¶z gezdirmenizi ÅŸiddetle tavsiye ediyorum. Biz burada bu mekanizmalarÄ±n Ã§alÄ±ÅŸma ÅŸekillerinden Ã§ok iÅŸimize yarayan kÄ±smÄ±nÄ± anlatmaya Ã§alÄ±ÅŸacaÄŸÄ±z. Ama linkini verdiÄŸim makalede bunlarÄ±n Ã§alÄ±ÅŸma ÅŸekillerini ayrÄ±ntÄ±lÄ± bir ÅŸekilde bulabilirsiniz.</p><p
style="text-align: justify;">Birinci olarak gÃ¶receÄŸimiz Ã§aÄŸÄ±rÄ±m mekanizmasÄ± <strong>register </strong>Ã§aÄŸÄ±rÄ±mÄ±dÄ±r. Delphi varsayalÄ±n olarak bÃ¼tÃ¼n fonksiyon ve metodlarda bu Ã§aÄŸÄ±rÄ±mÄ± kullanmaktadÄ±r. Normalde Dehlpi&#8217;de &#8220;register&#8221; ayrÄ±lmÄ±ÅŸ kelimesini fonksiyon ya da metodun sonuna eklemekle, fonksiyon ya da metodu bu Ã§aÄŸÄ±rÄ±m iÃ§in ayarlamÄ±ÅŸ oluruz. Fakat varsayÄ±lan olarak kullanÄ±ldÄ±ÄŸÄ± iÃ§in bunu yazmanÄ±za gerek yoktur:</p><pre class="brush: delphi">procedure RegisterCagirimliProcedure; register;</pre><p
style="text-align: justify;">Fonksiyon Ã§aÄŸÄ±rÄ±m mekanizmalarÄ± ile ilgili yazÄ±yÄ± okuduysanÄ±z en verimli ve performanslÄ± Ã§aÄŸÄ±rÄ±mÄ±n bu olduÄŸunu biliyorsunuzdur. Bu mekanizma ilk olarak Borland tarafÄ±ndan geliÅŸtirilip C++ Builder ve Delphi derleyicilerinde kullanÄ±ldÄ±. Åžu anda bildiÄŸim bÃ¼tÃ¼n C / C++ derleyicileri bu Ã§aÄŸÄ±rÄ±mÄ± desteklemektedir. C / C++ derleyicilerinde bu Ã§aÄŸÄ±rÄ±m<strong> __fastcall</strong> olarak isimlendirilmektedir.</p><p
style="text-align: justify;">Her ne kadar en hÄ±zlÄ± Ã§aÄŸÄ±rÄ±m __fastcall yani register olsa da ve Ã§oÄŸu derleyici tarafÄ±ndan desteklense de, belki de alÄ±ÅŸkanlÄ±klardan dolayÄ±, C / C++&#8217;da pek kullanÄ±lmamaktadÄ±r. Genelde Linux ve Windows&#8217;da ileride gelecek olan baÅŸka Ã§aÄŸÄ±rÄ±mlar kullanÄ±lmaktadÄ±r.</p><p
style="text-align: justify;">__fastcall yani register Ã§aÄŸÄ±rÄ±mlarÄ±, Microsoft&#8217;uÄ±n derleyicilerinde <strong>__msfastcall</strong> olarak baÅŸka bir biÃ§imi de almÄ±ÅŸtÄ±r. Fakat ÅŸu anda Delphi bu Ã§aÄŸÄ±rÄ±mÄ± desteklememektedir. UmarÄ±m ilerideki Delphi derleyicilerinde bunu gÃ¶rebiliriz. Fakat bu Ã§aÄŸÄ±rÄ±m __fastcall kadar bile yaygÄ±n ve fazla kullanÄ±lmadÄ±ÄŸÄ± iÃ§in ÅŸu anda anlattÄ±ÄŸÄ±mÄ±z Ã§evirim iÅŸlemi iÃ§in Ã§ok da Ã¶nemli deÄŸil. Hatta, eÄŸer bir kÃ¼tÃ¼phane bir Ã§ok dili desteklemek gibi bir gayesi varsa __fastcall Ã§aÄŸÄ±rÄ±mÄ±nÄ± da desteklememektedir.</p><p
style="text-align: justify;">KÄ±sacasÄ± bu Ã§aÄŸÄ±rÄ±mÄ± delphi&#8217;ye aktarmak iÃ§in hiÃ§ bir ÅŸey yapmamÄ±z gerekmiyor. Ã‡Ã¼nkÃ¼ delphi bunu varsayÄ±lan olarak kullanÄ±yor. Mesela aÅŸaÄŸÄ±daki C fonksiyonunu delphi&#8217;ye Ã§evirelim:</p><pre class="brush: c++">__fastcall int birFonksiyon(int i);</pre><pre class="brush: delphi">function BirFonksiyon(i: Integer): Integer;</pre><p
style="text-align: justify;">Ä°kinci Ã§aÄŸÄ±rÄ±m mekanizmamÄ±z <strong>__pascal</strong> yada delphi&#8217;de <strong>pascal</strong> Ã§aÄŸÄ±rÄ±mÄ±dÄ±r. Ki bu Ã§aÄŸÄ±rÄ±m Win 3.1 zamanÄ±ndan kalma eski bir Ã§aÄŸÄ±rÄ±mdÄ±r. Bu yÃ¼zden eÄŸer karÅŸÄ±laÅŸÄ±rsanÄ±z yapmanÄ±z gereken __pascal yerine pascal yazmalÄ±sÄ±nÄ±z.</p><p
style="text-align: justify;">ÃœÃ§Ã¼ncÃ¼ Ã§aÄŸÄ±rÄ±m mekanizmamÄ±z <strong>__stdcall</strong> ya da delphi&#8217;de <strong>stdcall</strong> Ã§aÄŸÄ±rÄ±mÄ±dÄ±r. Bu Ã§aÄŸÄ±rÄ±m, Windows iÅŸletim sisteminin varsayÄ±lan Ã§aÄŸÄ±rÄ±m mekanizmasÄ±dÄ±r. EÄŸer windows&#8217;a ait bir DLL&#8217;i kullanacaksak, bilinki %99 stdcall olarak tanÄ±mlanmÄ±ÅŸtÄ±r. __stdacall Ã§aÄŸÄ±rÄ±mÄ± derleyicilerde Ã§eÅŸitli takma adlar ile kullanÄ±lmaktadÄ±r. Genelde &#8220;WINAPI&#8221; kelimesi __stdcall iÃ§in kullanÄ±lmaktadÄ±r. Mesela aÅŸaÄŸÄ±daki Windows API&#8217;sinden bulunan fonksiyonu ÅŸÃ¶yle Ã§evireceÄŸiz:</p><pre class="brush: c++">WINAPI BOOLÂ ReleaseCapture(VOID);</pre><pre class="brush: delphi">function ReleaseCapture: Boolean; stdcall;</pre><p
style="text-align: justify;">YardÄ±m dosyalarÄ±nda bu fonksiyonun baÅŸÄ±nda WINAPI ya da __stdcall ifadesini gÃ¶rmesek de, biliyoruz ki bu bir Windows fonksiyonudur. Ã–yleyse bu fonksiyon stdcall Ã§aÄŸÄ±rÄ±mÄ±dÄ±r. Bu Ã§Ä±karÄ±m ile hem delphi hem de C kodunda bu Ã§aÄŸÄ±rÄ±mÄ± belli ettim.</p><p
style="text-align: justify;">DÃ¶rdÃ¼ncÃ¼ ve son Ã§aÄŸÄ±rÄ±mÄ±mÄ±z ise <strong>__cdecl</strong> ya da delphi&#8217;de <strong>cdecl</strong> Ã§aÄŸÄ±rÄ±mÄ±dÄ±r. Bu Ã§aÄŸÄ±rÄ±m C / C++ derleyicilerinin varsayÄ±lan Ã§aÄŸÄ±rÄ±mÄ±dÄ±r. EÄŸer C dosyalarÄ±nda hernangi bir Ã§aÄŸÄ±rÄ±m belirtilmemiÅŸ ise, bu fonksiyon cdecl olarak Ã§aÄŸÄ±rÄ±lacaktÄ±r. Yani aÅŸaÄŸÄ±daki fonksiyonlar aynÄ± ÅŸeyi ifade edip her iksinin de Ã§evirimi aÅŸaÄŸÄ±da gÃ¶sterilmektedir.</p><pre class="brush: c++">void bir_proc();
__cdecl void ikinici_proc();</pre><pre class="brush: delphi">procedure bir_proc; cdecl;
procedure ikinci_proc; cdecl;</pre><p>Ä°leride makrolarÄ± gÃ¶receÄŸiz. AÅŸaÄŸÄ±daki makro tanÄ±mlamalarÄ± da geÃ§erlidir ve kullanÄ±lmaktadÄ±r.</p><p>__stdcall = _stdcal = CALLBACK = WINAPI = APIENTRY = PASCAL = APIPRIVATE</p><p>__cdecl = _cdecl = WINAPIV</p><p>__fastcall = _fastcall</p><p>YukarÄ±da eÅŸitliklik ile ifade edilenleri birbirlerinin aynÄ±sÄ± olarak kabul edebilirsiniz.</p><h2>DLL KullanÄ±mÄ± ve Ã‡aÄŸÄ±rÄ±mlar</h2><p
style="text-align: justify;">Normalde bir DLL&#8217;den bir fonksiyonu kullanmak iÃ§in fonksiyonu nasÄ±l tanÄ±mlayacaÄŸÄ±mÄ±zÄ± bir hatÄ±rlayalÄ±m:</p><pre>
<pre class="brush: delphi">
const
  DLLDosyasi = &#039;birkutuphane.dll&#039;;
procedure bir_proc(); cdecl; external DLLDosyasi;
</pre></pre><p
style="text-align: justify;">Kendi DLL&#8217;imizi kullandÄ±ÄŸÄ±mÄ±zda fonksiyonu nasÄ±l tanÄ±mlayacaÄŸÄ±mÄ±zÄ± biliyoruz. Peki DLL&#8217;i biz yazmamÄ±ÅŸ isek ne yapacaÄŸÄ±z?</p><p
style="text-align: justify;">Bu durumda, eÄŸer herkes tarafÄ±ndan kullanÄ±labilir bir DLL dosyasÄ± ise, DLL saÄŸlayan firma, ekip, yazÄ±lÄ±mcÄ±, vs. DLL dosyasÄ± ile beraber bir &#8220;header&#8221; dosyasÄ± saÄŸlayacaktÄ±r.</p><p
style="text-align: justify;">Delphi&#8217;de, bildiÄŸiniz gibi, unit iki bloktan oluÅŸur. Birinci blok yani <strong>interface </strong>bloÄŸu, unit tarafÄ±ndan &#8220;unit dÄ±ÅŸÄ±nda&#8221; kullanÄ±lacak olan sÄ±nÄ±f, deÄŸiÅŸken, fonksiyon, vs. &#8216;den oluÅŸur. Ä°kinci blok yani <strong>implementation </strong>bloÄŸu ise, interface bloÄŸunda tanÄ±mlanmÄ±ÅŸ olan fonksiyon ve sÄ±nÄ±flarÄ±n esas kodlarÄ±ndan oluÅŸur. Yani esas Ã§alÄ±ÅŸtÄ±rÄ±lan kodlar implementation kÄ±smÄ±nda bulunur. AyrÄ±ca implementation&#8217;da tanÄ±mlÄ± herhangi bir deÄŸiÅŸken, fonksiyon, vs. eÄŸer interface&#8217;de tanÄ±mlÄ± deÄŸilse diÄŸer unitlerde gÃ¶rÃ¼nmezler ve kullanÄ±lamazlar.</p><p
style="text-align: justify;">C / C++ dosyalarÄ± da Delphi&#8217;nin unit dosya mantÄ±ÄŸÄ±nÄ±n aynÄ±sÄ±dÄ±r. Fakat Delphi&#8217;nin aksine C / C++ dosyalarÄ± tek parÃ§a halinde deÄŸil iki parÃ§a halinde tutulurlar. Delphi&#8217;de interface olarak ifade ettiÄŸimiz blok C &#8216;de &#8220;header&#8221; olarak ifade edilir ve &#8220;.h&#8221; uzantÄ±sÄ±na sahiptir. Nadir de olsa C++&#8217;da header dosyalarÄ± &#8220;.hpp&#8221; uzantÄ±sÄ± alabilirler. Delphi&#8217;de implementation olarak ifade edilen esas Ã§alÄ±ÅŸan kodlar ise C&#8217;de &#8220;.c&#8221; ve C++&#8217;da ise &#8220;.cpp&#8221; uzantÄ±sÄ± ile ifade edilen dosyalardadÄ±r.</p><p
style="text-align: justify;">Header dosyalarÄ±, ÅŸart olmasa da, genelde kÃ¼tÃ¼phanenin &#8220;include&#8221; adlÄ± klasÃ¶rÃ¼nde barÄ±ndÄ±rÄ±lmaktadÄ±r. KullanacaÄŸÄ±nÄ±z DLL&#8217;in header dosyasÄ± da bu veya bunun benzeri bir klasÃ¶rde bulunacaktÄ±r. Header dosyasÄ± olmadan Delphi Ã§evirimi yapmamÄ±z Ã§ok zor olacaktÄ±r. Hatta Ã¼st dÃ¼zey assembler bilginiz olmasÄ± gerekebilir. Bu yÃ¼zden DLL ile beraber en az bir adet header dosyasÄ±na sahip olduÄŸunuzu varsayÄ±yorum.</p><p
style="text-align: justify;">Bu baÅŸlÄ±k altÄ±nda esas olarak anlatmak istediÄŸim mevzuya ÅŸimdi geliyoruz.</p><p
style="text-align: justify;">DLL&#8217;e ait header dosyasÄ±na baktÄ±ÄŸÄ±mÄ±zda fonksiyonlarÄ±n hangi Ã§aÄŸÄ±rÄ±m mekanizmalarÄ±nÄ± kullandÄ±klarÄ±nÄ± gÃ¶rebiliyor ve anlayabiliyoruz. Fakat derlenmiÅŸ olan DLL dosyalarÄ±nda bu Ã§aÄŸÄ±rÄ±m mekanizmalarÄ±nÄ± belirten hernhangi bir iÅŸaret var mÄ±?</p><p
style="text-align: justify;">Bunun iÃ§in yardÄ±mcÄ± bir araca ihtiyaÃ§ duyacaÄŸÄ±z. AslÄ±nda TDump isimli ve delphi ile beraber gelen bir konsol uygulamasÄ± bulunmakta. Ancak konsol uygulamasÄ± yerine gÃ¶resel bir aracÄ± tercih ederim. Ama illaki tdump kullanmak isteyen olursa &#8220;-b&#8221; parametresi ile beraber kullanabilirsiniz. Her neyse, ihtiyacÄ±mÄ±z olan program &#8220;<a
href="http://www.dependencywalker.com/" target="_blank">Dependency Walker</a>&#8221; . Bu program ile DLL&#8217;de bulunan tÃ¼m fonksiyonlarÄ± isimleri ile beraber gÃ¶rebiliriz.</p><p
style="text-align: justify;">Peki header dosyasÄ±nda fonksiyonlar ayrÄ±ntÄ±lÄ± bir ÅŸekilde olmasÄ±na raÄŸmen neden ekstra bir araca ihtiyaÃ§ duyuyoruz. AslÄ±nda ekstra bir programa ihtiyacÄ±mÄ±z yok. Header dosyalarÄ± fazlasÄ±yla yeterlidir. Fakat bazen DLL&#8217;ler varsayÄ±lan ayarlarla derlenmemektedir. Bu da bize sorun Ã§Ä±karabilmektedir.</p><p
style="text-align: justify;">DLL&#8217;ler derlenirken fonksiyon isimleri Ã§eÅŸitli ekler alÄ±rlar. Bu ekler, fonksiyonun hangi Ã§aÄŸÄ±rÄ±mÄ± kullandÄ±ÄŸÄ±nÄ± belirler. Ama bazen bu varsayÄ±lan isimlendirmenin dÄ±ÅŸÄ±na Ã§Ä±kan kÃ¼tÃ¼phane yazÄ±lÄ±mcÄ±larÄ±, bÃ¼tÃ¼n ekleri kaldÄ±rabiliyorlar. Mesela cdecl fonksiyonlarÄ± Ã¶nlerinde &#8220;_&#8221;Â  iÅŸaretini barÄ±ndÄ±rÄ±rlar. Veya stdcall fonksiyonlarÄ± fonksiyon isiminden sonra &#8220;@&#8221; iÅŸareti ve parametrelerin boyutlarÄ±nÄ± iÃ§eren bir dizi ekten ibarettirler. Dependency Walker gibi programlar, bize fonksiyonlarÄ±n hangi isimlerden oluÅŸtuÄŸunu gÃ¶sterecektir. EÄŸer header dosyasÄ±nÄ± Delphi&#8217;ye hatasÄ±z aktardÄ±k fakat halen fonksiyonun bulunmadÄ±ÄŸÄ±na dair hata alÄ±yorsak demek ki isimlendirmeler yanlÄ±ÅŸ demektir. Bunun iÃ§in aÅŸaÄŸÄ±daki yÃ¶ntemi kullanmalÄ±yÄ±z:</p><pre class="brush: delphi">procedure BirProc; cdecl; external DLLDosyasi name &#039;_bir_proc&#039;;</pre><p
style="text-align: justify;">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi &#8220;external&#8221; direktifinin hemen sonuna bir boÅŸluk ile beraber bir <strong>name </strong>direktifi ekledik. Bu &#8220;name&#8221; direktifi ile DLL&#8217;deki fonksiyona direk olarak iÅŸaret etmiÅŸ oluyoruz. Bu tekniÄŸi sadece ihtiyaÃ§ dahilinde kullanabilirsiniz. Veya C / C++ ismi size hoÅŸ gelmedi ise fonksiyonun ismini Delphi&#8217;de kullanÄ±m adÄ±nÄ± deÄŸiÅŸtirmek iÃ§in kullanabilirsiniz.</p><p
style="text-align: justify;"><table
style="background-color: #e9eaeb; width: 100%;" border="0"><caption>Not</caption><tbody><tr><td
style="text-align: justify;">Bir tecrÃ¼bemi aktarmak istiyorum. EÄŸer C / C++&#8217;a fazla hakim deÄŸilseniz, muhtemelen header dosyalarÄ±nÄ± Ã§eviriken bir Ã§ok hata yapacaksÄ±nÄ±z. Bu durumda DLL&#8217;i statik olarak kullandÄ±ÄŸÄ±nÄ±zdan dolayÄ±, delphi programÄ± derleyecek ama Ã§alÄ±ÅŸtÄ±ramayacktÄ±r. Ve program donacaktÄ±r. Ã‡Ã¼nkÃ¼ istediÄŸi DLL iÃ§inde sizin tanÄ±mladÄ±ÄŸÄ±nÄ±z gibi bir fonksiyon bulamamÄ±ÅŸtÄ±r. Bunun yerine ilk baÅŸlarda, header dosyasÄ±nÄ±n Ã§evirimi doÄŸru bir ÅŸekilde Ã§evrilene kadar, DLL dosyasÄ±nÄ± dinamik olarak yÃ¼kleyin. Bu ÅŸekilde Ã§Ä±kan hatalarÄ±, hangi fonksiyon tanÄ±mlamasÄ±ndan kaynaklandÄ±ÄŸÄ±nÄ± belirleyebilirsiniz. Dinamik DLL yÃ¼klemesinin nasÄ±l yapÄ±ldÄ±ÄŸÄ±nÄ± internetten araÅŸtÄ±rarak bulabilirsiniz.</td></tr></tbody></table><table
style="background-color: #e9eaeb; width: 100%;" border="0"><caption>Not</caption><tbody><tr><td
style="text-align: justify;">Header dosyalarÄ±nÄ± Ã§evirmek iÃ§in aslÄ±nda JEDI kÃ¼tÃ¼phanesine ait bir araÃ§ bulunmaktadÄ±r. Fakat bu araÃ§ da tam olarak header dosyalarÄ±nÄ± Ã§evirememektedir. Daha doÄŸrusu yine burada anlattÄ±ÄŸÄ±mÄ±z bilgilere ihtiyaÃ§ duyacaksÄ±nÄ±z. Bu araÃ§ sadece Ã§ok bÃ¼yÃ¼k dosyalarda yazÄ±m kolaylÄ±ÄŸÄ± saÄŸlamak aÃ§Ä±sÄ±ndan bir kolaylÄ±k getirmektedir. AyrÄ±ca ileride anlatacÄŸÄ±mÄ±z konular iÃ§in bu araÃ§ yetersiz kalmaktadÄ±r. Bu araca Dr. Bob&#8217;un sitesinden ya da JEDI kÃ¼tÃ¼phanesinden eriÅŸebilirsiniz. (Header Conversation Tool)</td></tr></tbody></table><p
style="text-align: justify;">Ã‡aÄŸÄ±rÄ±m mekanizmalarÄ±na hakim olmak Delphi Ã§evirimi noktasÄ±nda size bÃ¼yÃ¼k kolaylÄ±k saÄŸlayacaktÄ±r. Bu yÃ¼zden bu konuyu ilk sÄ±raya aldÄ±m ve biraz da uzun tuttum.</p><h1>Veri Tipleri</h1><p
style="text-align: justify;">C / C++ kodlarÄ±, Ã§ok fazla pointer ile ilgili iÅŸlemleri barÄ±ndÄ±rmaktadÄ±r. Basit bir tip tanÄ±mlamasÄ±nda bile pointerlara ihtiyaÃ§ duyarsÄ±nÄ±z. Fakat C / C++&#8217;da bulunan bu pointer kullanÄ±mÄ± Delphi&#8217;ye geÃ§tiÄŸinde illaki pointer kalacak diye bir ÅŸart yoktur. KullanÄ±mda bu olay farklÄ±lÄ±k gÃ¶stermektedir.</p><p
style="text-align: justify;">Ä°lk Ã¶nce basit veri tiplerinden baÅŸlayalÄ±m. AÅŸaÄŸÄ±daki fonksiyona bir gÃ¶z atalÄ±m:</p><pre class="brush: c++">char* birfonksiyon(void);</pre><p
style="text-align: justify;">Burada &#8220;char*&#8221; olarak Ã§Ä±ktÄ± veren bir fonksiyonuz mevcut. C&#8217;de &#8220;*&#8221; iÅŸareti pointer tanÄ±mlamak ve Ã§arpÄ±m iÅŸlemlerini yapmak iÃ§in kullanÄ±lÄ±r. EÄŸer char, int gibi bir tip ile birlikte kullanÄ±lÄ±yorsa bu, pointer operatÃ¶rÃ¼dÃ¼r. Bu Ã¶rnekte &#8220;char*&#8221; ifadesi bir char iÅŸaretÃ§isini ifade eder. Bu Delphi&#8217;de PAnsiChar ile ifade edilir. PChar demiyorum Ã§Ã¼nkÃ¼ Delphi 2009 ile beraber artÄ±k PChar unicode oldu. Fakat buradaki &#8220;char&#8221; ansi olan bir char tipidir. Bunun Delphi karÅŸÄ±lÄ±ÄŸÄ±:</p><pre class="brush: delphi">function birfonksiyon: PAnsiChar; cdecl;</pre><p
style="text-align: justify;">olacaktÄ±r. Burada kullanÄ±lan C / C++ pointer&#8217;Ä± aynÄ± ÅŸekilde Delphi&#8217;de de pointer olarak geÃ§miÅŸtir. Fakat bazen C&#8217;de pointer&#8217;lar hem pointer tanÄ±mlamak iÃ§in, hem dizi tanÄ±mlamak iÃ§in hem de parametrelerde Ã§Ä±kÄ±ÅŸ iÃ§in kullanÄ±labiliyor. BunlarÄ±n ayÄ±rÄ±mÄ±nÄ± zamanla ve tecrÃ¼beyle kazanacaksÄ±nÄ±z. AÅŸaÄŸÄ±da referans olarak kullanabileceÄŸiniz bir tablo gÃ¶zÃ¼kmektedir. Bu tabloyu kullandÄ±kÃ§a artÄ±k aÅŸina olup tekrar dÃ¶nÃ¼p bakmayacaÄŸÄ±nÄ±zÄ± da zannediyorum. Ama ÅŸimdi her birine birer birer gÃ¶z atmanÄ±zda yarar var.</p><table
border="1"><tbody><tr><th>C / C++ Tipi</th><th>Delphi KarÅŸÄ±lÄ±ÄŸÄ±</th><th>Delphi 2009 Alternatifi</th></tr><tr><td>char</td><td>AnsiChar</td><td></td></tr><tr><td>char*</td><td>PAnsiChar</td><td></td></tr><tr><td>wchar_t</td><td>WideChar</td><td>Char</td></tr><tr><td>wchar_t*</td><td>PWideChar</td><td>PChar</td></tr><tr><td>signed char</td><td>ShortInt</td><td></td></tr><tr><td>unsigned char</td><td>Byte</td><td></td></tr><tr><td>LPSTR veya PSTR</td><td>PAnsiChar</td><td></td></tr><tr><td>LPWSTR veya PWSTR</td><td>PWideChar</td><td>PChar</td></tr><tr><td>void*</td><td>Pointer</td><td></td></tr><tr><td>bool</td><td>Boolean</td><td></td></tr><tr><td>float</td><td>Single</td><td></td></tr><tr><td>double</td><td>Double</td><td></td></tr><tr><td>long double</td><td>Extended</td><td></td></tr><tr><td>int</td><td>Integer</td><td></td></tr><tr><td>signed int</td><td>Integer</td><td></td></tr><tr><td>unsigned int</td><td>Cardinal</td><td></td></tr><tr><td>UINT</td><td>Cardinal</td><td></td></tr><tr><td>unsigned long</td><td>Cardinal</td><td></td></tr><tr><td>unsigned long int</td><td>Cardinal</td><td></td></tr><tr><td>unsigned</td><td>Cardinal</td><td></td></tr><tr><td>long</td><td>LongInt</td><td></td></tr><tr><td>signed long</td><td>LongInt</td><td></td></tr><tr><td>long int</td><td>LongInt</td><td></td></tr><tr><td>DWORD</td><td>Cardinal veya DWORD</td><td></td></tr><tr><td>QWORD</td><td>QWORD</td><td></td></tr><tr><td>WORD</td><td>Word</td><td></td></tr><tr><td>unsigned short</td><td>Word</td><td></td></tr><tr><td>unsigned short int</td><td>Word</td><td></td></tr><tr><td>short</td><td>SmallInt</td><td></td></tr><tr><td>short int</td><td>SmallInt</td><td></td></tr><tr><td>signed short</td><td>SmallInt</td><td></td></tr></tbody></table><p
style="text-align: justify;">Tabloyu incelerseniz Ã§oÄŸu tipin birbirinin aynÄ±sÄ± olduÄŸunu anlarsÄ±nÄ±z. Bu yÃ¼zden tablo biraz uzunca oldu. Bunun nedeni C / C++&#8217;da bolca makro denilen yapÄ±larÄ±n kullanÄ±lmasÄ±dÄ±r. Makrolar ile ilgili iÅŸlemleri ileride anlatacaÄŸÄ±mÄ±zdan ÅŸimdilik burada kÄ±sa kesiyoruz.</p><p
style="text-align: justify;">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi string yerine PChar yada PAnsiChar kullanÄ±lmakta. Tabloda ayrÄ±ca Delphi 2009 ve yukarÄ±sÄ±nda kullanÄ±lmak Ã¼zere verdiÄŸim alternetifler de mevcut.</p><table
style="background-color: #e9eaeb; width: 100%;" border="0"><caption>Bir TÃ¼yo</caption><tbody><tr><td
style="text-align: justify;">Tabi burada verilmeyen bir Ã§ok tip olabilir. Ama temel manada bunlar bize referans olacaktÄ±r. DiÄŸer tipler iÃ§in bir tÃ¼yomuz ÅŸÃ¶yle olacaktÄ±r. Mesela UINT gibi makro bir tipin ifade ettiÄŸi tipi,deÄŸeri bulabilmek iÃ§in C++ Builder gibi herhangi bir derleyeci size kafi gelecektir. Tek yapmanÄ±z gereken aÅŸaÄŸÄ±daki gibi bir yapÄ±yÄ±, derleyicinin kÃ¼tÃ¼phane dosyalarÄ±nda arattÄ±rÄ±p bulmanÄ±zdÄ±r.<pre class="brush: c++">#define UINT unsigned int</pre><p
style="text-align: justify;">C++ Builder iÃ§in, sadece Ctrl ile tipin Ã¼zerine tÄ±klamÄ±nÄ±z kafidir. YukarÄ±daki ifadede UINT makrosu, &#8220;unsigned int&#8221; olarak tanÄ±mlanmÄ±ÅŸtÄ±r. Geriye kalan sadece &#8220;unsigned int&#8221; iÃ§in tablodan Delphi karÅŸÄ±lÄ±ÄŸÄ±nÄ± Ã¶ÄŸrenmektir.</p></td></tr></tbody></table><p
style="text-align: justify;">Veri tipleri ile ilgili zamanÄ± geldikÃ§e yine deÄŸineceÄŸiz. Ama giriÅŸ iÃ§in bu kadarlÄ±k bilgi yeterli.</p><h1>Makrolar</h1><p
style="text-align: justify;">Diyeceksiniz ki, ne oluyor C dersine mi baÅŸladÄ±k? EÄŸer bir dilden diÄŸer dile Ã§evirim yapmak istiyorsanÄ±z her iki dilin de incelikleri bilmeniz gerekmektedir. Tabi biz burada bir C kitabÄ± yazacak deÄŸiliz. Bunun yerine mÃ¼mkÃ¼n olduÄŸunca kÄ±sa tutup pÃ¼f noktalarÄ±nÄ± vermeye Ã§alÄ±ÅŸÄ±yorum. Fakat, yeri gelecek bir C kitabÄ±nÄ± karÄ±ÅŸtÄ±rmanÄ±z gerekebilecek veya C ile ilgili bir siteyi&#8230;</p><p
style="text-align: justify;">Makrolar C / C++ derleyicilerine, derlemeden hemen Ã¶nce yapÄ±lacak olan iÅŸlemleri bildirir. Bir nevi Delphi&#8217;deki {$ ..} derleyici direktiflerine benzeselerde bunlar daha karmaÅŸÄ±klardÄ±r. Ã–nemli nokta, makrolarÄ±n derlemeden hemen Ã¶nce Ã§alÄ±ÅŸtÄ±rÄ±lmasÄ±dÄ±r ve derlemeye dahil olmamasÄ±dÄ±r. Bu yÃ¼zden C / C++ derleyicileri precompile denilen bir iÅŸleme tabi tutulurlar. Bu da C / C++ derleyicilerinin neden bu kadar yavaÅŸ derlediklerinin bir sebebidir. EÄŸer C / C++ ile bÃ¼yÃ¼k bir programÄ± derlememiÅŸ iseniz hala, Delphi gibi 1-2 sn iÃ§inde derlediÄŸini zannedersiniz. Halbuki C/C++&#8217;da Ã¶mrÃ¼nÃ¼z yarÄ±sÄ± derlemekle geÃ§er <img
src='http://www.diyezon.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><p
style="text-align: justify;">AÅŸaÄŸÄ±da tanÄ±mlÄ± basit bir makro gÃ¶rÃ¼yorusunuz:</p><pre class="brush: c++">#define BIRMAKRO MakronunDegeri</pre><p
style="text-align: justify;">Makro burada gÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi #define ile tanÄ±mlanÄ±yor. Delphide olduÄŸu gibi #ifdef, #ifndef, #endif gibi ifadelerle bu makronun tanÄ±mlÄ± olup olmadÄ±ÄŸÄ± kontrol edilebilir.</p><p
style="text-align: justify;">Peki bu makro delphi&#8217;ye geÃ§irilecek mi? Belki evet belki hayÄ±r. EÄŸer makro bir fonksiyonu tanÄ±mlÄ±yorsa bu durumda makroyu delphide tanÄ±mlamalÄ±sÄ±nÄ±z. Aksi taktirde makronun deÄŸeri sizin iÃ§in yeterlidir. Makroyu geÃ§rimenize gerek yok.</p><p
style="text-align: justify;">EÄŸer Ã¶nceki konudaki tÃ¼yoyu okudu iseniz makrolarÄ±n gerÃ§ek deÄŸerlerine nasÄ±l ulaÅŸacaÄŸÄ±mÄ±zÄ± biliyoruz. Mesela aÅŸaÄŸÄ±daki makroyu birebir delphi&#8217;ye geÃ§irmeye luzum yoktur:</p><p>C:</p><pre>
<pre class="brush: c++">#define size_t unsigned int
__stdcall size_t getSize();</pre></pre><p>Delphi:</p><pre class="brush: delphi">function getSize: Cardinal; stdcall;</pre><p
style="text-align: justify;">Ama isterseniz size_t makrosunu bir tip olarak tanÄ±mlayabilirsiniz de:</p><pre class="brush: delphi">size_t = Cardinal;</pre><p
style="text-align: justify;">Ama lÃ¼zum yok. Peki hangi makrolarÄ± delphi&#8217;ye Ã§evirmemiz gerekli? Åžimdiye kadarki tecrÃ¼beme gÃ¶re genelde fonksiyon makrolarÄ±nÄ± geÃ§rimek yeterli. AÅŸaÄŸÄ±da Ã¶rnek bir fonksyion makrosu mevcut ve devamÄ±nda delphi kodlarÄ±nÄ± bulabilirsiniz:</p><pre class="brush: c++">#define Fonksiyon(Msg) MessageBox(NULL, Msg, NULL, NULL)</pre><pre>
<pre class="brush: delphi">procedure Fonksiyon(Msg: PChar); inline;
begin
  MessageBox(0, Msg, &#039;&#039;, 0);
end;</pre></pre><p
style="text-align: justify;">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi sadece &#8220;<strong>inline</strong>;&#8221; olarak tanÄ±mlamamÄ±z aynÄ± etkiyi yapacaktÄ±r. Ã‡Ã¼nkÃ¼ &#8220;inline&#8221; direktifi de makro gibi fonksiyonun Ã§aÄŸrÄ±ldÄ±ÄŸÄ± yerde Ã§alÄ±ÅŸtÄ±rÄ±lÄ±r. Inline ve makro fonksiyonlar iÃ§in internette bir Ã§ok makale bulabilirsiniz.</p><p
style="text-align: justify;">Bunun dÄ±ÅŸÄ±nda makrolar ile iligli olarak ÅŸunu sÃ¶ylemek istiyorum. Ã–nceden de dediÄŸim gibi her makronun bire bir Delphi&#8217;ye Ã§evrilmesine gerek yoktur. Makro fonksiyonlarÄ±n haricinde bir de bazen makro sabitler de tanÄ±mlanabilir. Mesela:</p><pre>
<pre class="brush: c++">#define ei_NONE 0
#define ei_WRITE 1
#define ei_READ 2
#define ei_CREATE 3</pre></pre><p
style="text-align: justify;">Bu tanÄ±mlamalarÄ± ister const ile tek tek eÅŸitleyerek yaparsÄ±nÄ±z isterseniz enumerator tanÄ±mlarsÄ±nÄ±z. Biz ikisini de gÃ¶relim:</p><pre>
<pre class="brush: delphi">//const ile
const
  ei_NONE = 0;
  ei_WRITE = 1;
  ei_READ = 2;
  ei_CREATE = 3;
//enumerator ile
type
  Tei = (ei_NONE = 0, ei_WRITE = 1, ei_READ = 2, ei_CREATE = 3);</pre></pre><p>Tercih size kalmÄ±ÅŸ&#8230;</p><p
style="text-align: justify;">Ã‡ok karmaÅŸÄ±k makrolar geldiÄŸinde internetten veya bir c kitabÄ±ndan yardÄ±m alabilirsiniz. Fakat bu kadarlÄ±k bilgi sizi fazlasÄ±yla idare edecektir.</p><h1>Gelecek Makalede</h1><p
style="text-align: justify;">Daha yapacaÄŸÄ±mÄ±z Ã§ok iÅŸler olacak. Åžimdilik bu verdiÄŸimiz bilgiler ile kendiniz Ã§evirimler deneyebilirsiniz. Fakat, daha gÃ¶rememiz gereken Ã§ok Ã¶nemli konular mevcut. Ã–zellikle fonksiyon parametreleri baÅŸlÄ± baÅŸÄ±na bir konu baÅŸlÄ±ÄŸÄ±.</p><p
style="text-align: justify;">Bununla beraber bu makale serisinde sadece DLL kullanÄ±mÄ±nÄ± gÃ¶rmeyeceÄŸiz. Gelecek makalelerde DLL kullanmadan C obje dosyalarÄ±nÄ± direk olarak delphi&#8217;ye gÃ¶meceÄŸiz. BÃ¶ylece programÄ±nÄ±zÄ±n yanÄ±nda ek bir DLL verme zorunluluÄŸunuzda kalkacak. Tabi bu konu baÅŸlÄ± baÅŸÄ±na bir makale bÃ¶lÃ¼mÃ¼ olacaktÄ±r.</p><p
style="text-align: justify;">Yine gelecek makalelerde hedear dosyalarÄ± haricindeki, implementation olarak ifade ettiÄŸimiz kÄ±sÄ±mlarÄ± da sÄ±fÄ±rdan Delphi&#8217;ye nasÄ±l Ã§evrileceÄŸinden bahsedeceÄŸiz. Daha doÄŸrusu yine bazÄ± pÃ¼f noktalara deÄŸineceÄŸiz. Yoksa tÃ¼m gramerin nasÄ±l Ã§evrileceÄŸini anlatmak biraz uzun ve sÄ±kÄ±cÄ± olabilir.</p><p
style="text-align: justify;">Bu bÃ¶lÃ¼mlÃ¼k bu kadar.</p><p
style="text-align: justify;">Fikir, eleÅŸtiri ve Ã¶nerilerinizi bekliyorum.</p><p
style="text-align: center;"><strong>Fatih Tolga Ata &#8211; 2009</strong></p> ]]></content:encoded> <wfw:commentRss>http://www.diyezon.com/c-den-delphiye-kod-cevirme-klavuzu-1/feed/</wfw:commentRss> <slash:comments>7</slash:comments> </item> <item><title>Stream&#8217;de UzmanlaÅŸalÄ±m&#8230; (BÃ¶lÃ¼m 2)</title><link>http://www.diyezon.com/streamde-uzmanlasalim-bolum-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=streamde-uzmanlasalim-bolum-2</link> <comments>http://www.diyezon.com/streamde-uzmanlasalim-bolum-2/#comments</comments> <pubDate>Mon, 16 Feb 2009 22:19:27 +0000</pubDate> <dc:creator>Fatih Tolga Ata</dc:creator> <category><![CDATA[Delphi]]></category> <category><![CDATA[BinaryReader]]></category> <category><![CDATA[BinaryWriter]]></category> <category><![CDATA[BufferedStream]]></category> <category><![CDATA[MemoryStream]]></category> <category><![CDATA[stream]]></category> <category><![CDATA[StreamReader]]></category> <category><![CDATA[StreamWriter]]></category> <category><![CDATA[TBlobStream]]></category> <category><![CDATA[TFileStream]]></category> <category><![CDATA[TMemoryStream]]></category> <category><![CDATA[TResourceStream]]></category> <category><![CDATA[TStream]]></category><guid
isPermaLink="false">http://www.diyezon.com/?p=99</guid> <description><![CDATA[GeÃ§en bÃ¶lÃ¼mde stream&#8217;e giriÅŸ yaptÄ±k. Ve deÄŸiÅŸik veri tipleri ile stream Ã¼zerindeki okuma ve yazma iÅŸlemlerini gÃ¶rdÃ¼k. Bu bÃ¶lÃ¼mde stream kullanÄ±mÄ±nÄ±n sadece dosya okumak-yazmak olmadÄ±ÄŸÄ±nÄ± da gÃ¶receÄŸiz. AyrÄ±ca .net ve vcl.net ortamÄ±nda stream kullanÄ±mÄ±ndan da bahsetmeye Ã§alÄ±ÅŸacaÄŸÄ±z. HafÄ±za BÃ¶lgesinde Stream KullanÄ±mÄ± Takdir edersiniz ki en hÄ±zlÄ± stream verisi hafÄ±zada bulunan stream verisidir. Yani bir hafÄ±za [...]]]></description> <content:encoded><![CDATA[<p
align="justify">GeÃ§en bÃ¶lÃ¼mde stream&#8217;e giriÅŸ yaptÄ±k. Ve deÄŸiÅŸik veri tipleri ile stream Ã¼zerindeki okuma ve yazma iÅŸlemlerini gÃ¶rdÃ¼k. Bu bÃ¶lÃ¼mde stream kullanÄ±mÄ±nÄ±n sadece dosya okumak-yazmak olmadÄ±ÄŸÄ±nÄ± da gÃ¶receÄŸiz. AyrÄ±ca .net ve vcl.net ortamÄ±nda stream kullanÄ±mÄ±ndan da bahsetmeye Ã§alÄ±ÅŸacaÄŸÄ±z.</p><p><span
id="more-99"></span></p><h1>HafÄ±za BÃ¶lgesinde Stream KullanÄ±mÄ±</h1><p
align="justify">Takdir edersiniz ki en hÄ±zlÄ± stream verisi hafÄ±zada bulunan stream verisidir. Yani bir hafÄ±za stream nesnesi her halukarda okuma-yazma iÅŸlemleri dosya ve veritabanÄ±ndan hÄ±zlÄ± Ã§alÄ±ÅŸacaktÄ±r. Bu durumda eÄŸer bir stream ile Ã§ok fazla okuma-yazma iÅŸlemleri gerÃ§ekleÅŸtiriliyorsa, ilk baÅŸta bir hafÄ±za streami kullanÄ±lmalÄ± ve stream ile iÅŸimiz bitip son durumu kaydetmek istediÄŸimizde bu hafÄ±za streaminden baÅŸka bir stream nesnesine aktarÄ±m yapÄ±lmasÄ± en doÄŸru iÅŸlem olacaktÄ±r. AynÄ± ÅŸekilde stream verisi Ã¼zerinde Ã§ok miktarda Seek iÅŸlemi yani stream iÅŸaretÃ§isinin pozisyonunu deÄŸiÅŸtirme iÅŸlemi gerÃ§ekleÅŸtiriyorsanÄ±z, bu durumda yine stream verisinin tamamÄ±nÄ± bir hafÄ±za bÃ¶lgesine aktarmalÄ±sÄ±nÄ±z.</p><p>AÅŸaÄŸÄ±daki Ã¶rneÄŸe gÃ¶z atalÄ±m:</p><pre>
<pre class="brush: delphi">
procedure TForm1.Button1Click(Sender: TObject);
var
  Mem: TMemoryStream;
  writebuffer, readbuffer: AnsiString;
begin
  Mem := TMemoryStream.Create;
  try
    writebuffer := &#039;Diyezon&#039;;
    Mem.WriteBuffer(writebuffer[1], Length(writebuffer));
    Mem.Position := 0;
    SetLength(readbuffer, Length(writebuffer));
    Mem.ReadBuffer(readbuffer[1], Length(readbuffer));
    ShowMessage(readbuffer);
  finally
    Mem.Free;
  end;
end;
</pre></pre><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi TMemoryStream&#8217;in Create oluÅŸturucusu hiÃ§ bir parametre almÄ±yor. Burada ekstradan yazma iÅŸleminden sonra Position := 0 ile stream iÅŸaretÃ§isini baÅŸa getiriyoruz. &Ccedil;Ã¼nkÃ¼ yazma iÅŸleminin sonunda iÅŸaretÃ§i pozisyonu kayacaktÄ±r. Okuma iÅŸlemini yapabilmemiz iÃ§in yine iÅŸaretÃ§iyi baÅŸa getirip okutuyoruz. AynÄ± iÅŸlemi Seek metodu ile de yapabiliriz. Ek bir not olarak, Seek metodu Position&#8217;dan daha hÄ±zlÄ± Ã§alÄ±ÅŸmaktadÄ±r.</p><p
align="justify">HafÄ±za streami kullanmak, oluÅŸturulmasÄ± esnasÄ±nda hiÃ§ bir parametre gerektirmediÄŸinden, diÄŸerlerine nazaran daha kolay ve pratiktir. Bu yÃ¼zden yapacaÄŸÄ±mÄ±z yÃ¼ksek yoÄŸunluktaki stream iÅŸlemlerini TMemoryStream ile yapmamÄ±z bizim yararÄ±mÄ±za olacaktÄ±r. Ã–zellikle Seek iÅŸlemlerinde yani pozisyon deÄŸiÅŸtirme iÅŸlemlerinde hafÄ±zadan faydalanmak Ã¶nemli bir performans artÄ±ÅŸÄ±na sebep olacaktÄ±r.</p><h1>Stream&#8217;lerin AktarÄ±mÄ± ve KopyalanmasÄ±</h1><p
align="justify">Stream verileri ile okuma-yazma iÅŸlemlerinden sonra yapÄ±lan en Ã¶nemli iÅŸlem de bir stream&#8217;in baÅŸka bir stream verisi Ã¼zerine aktarÄ±lmasÄ±dÄ±r. Mesela bir dosyayÄ± hafÄ±zaya almak isteyebilirsiniz. Veya hafÄ±zadaki bir veriyi veritabanÄ±na aktarmak isteyebilirsiniz. Bu durumda her stream fonksiyonunda bulunan CopyFrom metodu kullanÄ±lÄ±r.</p><p
align="justify">AktarÄ±m iÅŸleminde basit bir metodu kullanmaktan Ã¶te, bir noktaya dikkat edilmesi ÅŸarttÄ±r. CopyFrom metodu ve bunun gibi bir Ã§ok metod, stream iÅŸaretÃ§isinin bulunduÄŸu pozisyondan itibaren iÅŸlemeye baÅŸlarlar. AÅŸaÄŸÄ±daki Ã¶rneÄŸe bir gÃ¶z atalÄ±m:</p><pre>
<pre class="brush: delphi">
procedure TForm1.Button1Click(Sender: TObject);
var
  Mem: TMemoryStream;
  F: TFileStream;
  //Mem, F: TStream; ÅŸeklinden de yazÄ±labilirdi...
  buffer: AnsiString;
begin
  Mem := TMemoryStream.Create;
  F := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmCreate or fmShareDenyNone);
  try
    buffer := &#039;Diyezon&#039;;
    Mem.WriteBuffer(buffer[1], Length(buffer));
    //karakter katarÄ±mÄ±zÄ± hafÄ±zaya aldÄ±k.

    Mem.Position := 0; //Ã–nemli!!!!

    F.CopyFrom(Mem, Mem.Size);
  finally
    Mem.Free;
    F.Free;
  end;
end;
</pre></pre><p
align="justify">Ä°lk yaptÄ±ÄŸÄ±mÄ±z iÅŸlem bir karakter dizisini hafÄ±zaya almak oldu. ArdÄ±nda bu hafÄ±za streamini dosya Ã¼zerine kopyaladÄ±k. Burada dikkat edilmesi gereken nokta Position := 0 kÄ±smÄ±dÄ±r. HafÄ±zaya karakter dizisinin yazÄ±lmasÄ±ndan sonra stream iÅŸaretÃ§isi sona kayar. BÃ¶ylece sonrasÄ±nda gelen CopyFrom gibi metodlar bu pozisyondan itibaren iÅŸlem yapmaya baÅŸlarlar. Ä°ÅŸaretÃ§i sonda olduÄŸu iÃ§in CopyFrom kopyalayamaz ve bir istisna hatasÄ± Ã§Ä±karÄ±r. Ä°ÅŸte bunu Ã¶nlemek iÃ§in iÅŸaretÃ§iyi baÅŸa alÄ±yoruz ve hafÄ±za streaminin tamamÄ±nÄ± dosya Ã¼zerine aktarÄ±yoruz.</p><p
align="justify">KÄ±sacasÄ± CopyFrom metodu, kopyalanacak olan streamin iÅŸaretÃ§i pozisyonundan itibaren, sizin belirlediÄŸiniz uzunluk kadar stream&#8217;den okur ve diÄŸer streame aktarÄ±r. Tek dikkat etmemiz gereken nokta kopyalayacaÄŸÄ±mÄ±z kaynak stream&#8217;in mevcut iÅŸaretÃ§i poziyonudur. EÄŸer iÅŸaretÃ§i poziyonu sonda ise CopyFrom kaynak stream&#8217;den veri okuyamayacak ve hata meydana gelecektir.</p></p><h1>Nesneler ve BileÅŸenleri Okuyup Yazmak</h1><p
align="justify">Nesneleri, stream Ã¼zerine yazmak denildiÄŸinde ilk akla gelen record verileri gibi okuyup yazmaktÄ±r. Halbuki nesneler, her ne kadar benzese de, record verilerinden Ã§ok farklÄ±dÄ±r ve karÄ±ÅŸÄ±ktÄ±r. Bu yÃ¼zden direk olarak bir sÄ±nÄ±f ya da nesne stream Ã¼zerine aktarÄ±lamaz. Ancak sizin belirlediÄŸiniz kÄ±sÄ±mlarÄ± ayrÄ± ayrÄ±, Ã¶nceden Ã¶ÄŸrendiÄŸimiz okuma-yazma iÅŸlemleri ile halledebilirsiniz.</p><p
align="justify">Fakat bileÅŸenlerde durum biraz farklÄ±dÄ±r. Daha doÄŸrusu TPersistent sÄ±nÄ±fÄ±ndan tÃ¼reyen bÃ¼tÃ¼n sÄ±nÄ±flarda durum biraz farklÄ±dÄ±r. TStream sÄ±nÄ±fÄ±nda, bileÅŸenlerin Ã¶zelliklerini stream Ã¼zerine alabilmek iÃ§in ReadComponent ve WriteComponent metodlarÄ± mevcuttur. Bu metodlar sayesinde bileÅŸenler stream verileri Ã¼zerine aktarÄ±labilirler. Ki, Delphi IDE&#8217;si bunu bol bol kullanmaktadÄ±r. EÄŸer bileÅŸen yazÄ±mÄ± ile ilgili 3 bÃ¶lÃ¼mlÃ¼k makaleyi okumuÅŸ iseniz bileÅŸenlerde bir Ã¶zelliÄŸe kaydedebilme Ã¶zelliÄŸi kazandÄ±rmÄ±ÅŸtÄ±k. Yani Ã¶zelliÄŸin kaydedebilme Ã¶zelliÄŸi yoksa stream Ã¼zerine aktarÄ±lamazlar. Ã–zelliklerin kaydedilebilme iÅŸlemine burada deÄŸinmeyeceÄŸiz. Ama isterseniz, bileÅŸen yazÄ±mÄ± ile ilgili makaledeki kolleksiyon ve binary Ã¶zellikler kÄ±smÄ±na gÃ¶z atabilirsiniz.</p><p
align="justify">BileÅŸenlere bu Ã¶zelliÄŸi kazandÄ±ran TPersistent sÄ±nÄ±fÄ±dÄ±r. TPersistent sÄ±nÄ±fÄ± ile ilgili daha fazla bilgi alabilmek iÃ§in yardÄ±m dosyalarÄ±na gÃ¶z atabilirsiniz.</p><p>Yeni bir form aÃ§alÄ±m ve bir button ekleyelim. Buttonun OnClick olayÄ±na aÅŸaÄŸÄ±daki kodlarÄ± yerleÅŸtirelim:</p><pre>
<pre class="brush: delphi">
procedure TForm1.Button1Click(Sender: TObject);
var
  Mem: TMemoryStream;
  F: TFileStream;
begin
  Mem := TMemoryStream.Create;
  F := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmCreate or fmShareDenyNone);
  try
    Mem.WriteComponent(Button1);

    Mem.Position := 0; //Ã–nemli!!!!

    F.CopyFrom(Mem, Mem.Size);
  finally
    Mem.Free;
    F.Free;
  end;
end;
</pre></pre><p
align="justify">Bu programÄ± Ã§alÄ±ÅŸtÄ±rÄ±p button&#8217;a basarsanÄ±z, C: bÃ¶lÃ¼mde deneme.txt isimli bir dosya gÃ¶receksiniz. Bu dosyayÄ± bir hex editor ile aÃ§Ä±p kontrol edebilirsiniz. Ama dosyaya baktÄ±ÄŸÄ±nÄ±zda TButton&#8217;a ait tÃ¼m Ã¶zelliklerin olmadÄ±ÄŸÄ±nÄ± gÃ¶receksiniz. &Ccedil;Ã¼nkÃ¼ burada sadece bileÅŸenin deÄŸiÅŸmiÅŸ olan Ã¶zellikleri kaydedilir. Her Ã¶zellik bir default deÄŸere sahiptir. Ve bu deÄŸer deÄŸiÅŸmiÅŸ ise, WriteComponent metodu bunu stream Ã¼zerine yazacaktÄ±r.</p><p
align="justify">Åžimdi bu dosyadaki Button1 bileÅŸenini okutalÄ±m ve form Ã¼zerinde oluÅŸturalÄ±m. Bunun iÃ§in yeni bir uygulama aÃ§alÄ±m ve iÃ§inde Button1 isimli bir button olmamasÄ±na Ã¶zen gÃ¶sterelim. &Ccedil;Ã¼nkÃ¼ birazdan bu bileÅŸeni dosyadan biz oluÅŸturacaÄŸÄ±z.</p><p
align="justify">Form Ã¼zerine bir button ekleyelim ve ismine Button2 diyelim ve Caption olarak &quot;bileÅŸeni dosyadan oku&quot; gibi bir ÅŸey yazalÄ±m. ArdÄ±ndan buttonun OnClick olayÄ±na aÅŸaÄŸÄ±daki kodlarÄ± yerleÅŸtirilem:</p><pre>
<pre class="brush: delphi">
procedure TForm1.Button2Click(Sender: TObject);
var
  F: TFileStream;
  Button1: TButton;
begin
  F := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmOpenRead or fmShareDenyNone);
  try
    Button1 := TButton.Create(Self);
    Button1.Parent := Self;
    F.ReadComponent(Button1);
  finally
    F.Free;
  end;
end;
</pre></pre><p
align="justify">ProgramÄ± Ã§alÄ±ÅŸtÄ±rÄ±p Button2&#8242;ye tÄ±klarsanÄ±z form Ã¼zerinde Ã¶nceden kaydettiÄŸimiz Button1 bileÅŸenini gÃ¶receksiniz.</p><p
align="justify">Ã–nceden de dediÄŸimiz gibi TPersistent olmayan nesneleri direk olarak stream olarak yazmak ve okumak mÃ¼mkÃ¼n deÄŸildir. Fakat kendinizin tanÄ±mlayacaÄŸÄ± formatta, stream&#8217;den okuma ve stream&#8217;e yazma gibi fonksiyonlar ile nesnelerinize bu Ã¶zelliÄŸi kazandÄ±rabilirsiniz. Zaten TPersistent sÄ±nÄ±fÄ±nÄ±n da yaptÄ±ÄŸÄ± iÅŸlem budur. TPersistent sÄ±nÄ±fÄ±na fazla girmek istemiyorum, fakat merakÄ± olanlar TPersistent ile beraber TFiler, TReader gibi sÄ±nÄ±flara yardÄ±mdan gÃ¶z atabilirler.</p><p
align="justify">Ek olarak bu konuda sÃ¶yleyebileceÄŸim bir tecrÃ¼bem de ÅŸudur. Ä°ster VCL iÃ§inde olsun, ister baÅŸka bir yerden bulacaÄŸÄ±nÄ±z bir bileÅŸen veya bir sÄ±nÄ±f olsun, eÄŸer stream ile Ã§alÄ±ÅŸÄ±yorlarsa ÅŸu 4 metod bunlarda bulunacaktÄ±r. LoadFromStream, LoadFromFile, SaveToStream, SaveToFile.</p><p
align="justify">Buna tecrÃ¼be dedim Ã§Ã¼nkÃ¼ literatÃ¼rde bu metodlar aynÄ± isim ve parametrelerle bulunacak diye bir ÅŸart yoktur. Fakat VCL&#8217;de bulunan bileÅŸenlerde bolca kullanÄ±lan bu metodlar, diÄŸer 3. parti bileÅŸen ve sÄ±nÄ±flarda da kolaylÄ±k ve alÄ±ÅŸkanlÄ±k olmasÄ± aÃ§Ä±sÄ±ndan isimlerini ve yapÄ±larÄ±nÄ± korumuÅŸtur. EÄŸer bir sÄ±nÄ±f stream ile iÅŸlem yapÄ±yorsa bilinki bu sÄ±nÄ±fta, yukarÄ±da bahsettiÄŸimiz 4 metod bulunacaktÄ±r.</p><p
align="justify">Sizler de yazacaÄŸÄ±nÄ±z sÄ±nÄ±flarda bu metodlarÄ± aynÄ± isim ve yapÄ±da kullanÄ±rsanÄ±z, sÄ±nÄ±fÄ±nÄ±zÄ± ya da bileÅŸeninizi kullanacak olan kiÅŸiler zorlanmayacaktÄ±r. Bu metodlarÄ±n tanÄ±mlamasÄ±nÄ± VCL&#8217;de herhangi bir sÄ±nÄ±f ya da bileÅŸenin tanÄ±mlamasÄ±ndan kopyala yapÄ±ÅŸtÄ±r ile alabilirsiniz. Sadece burada deÄŸiÅŸecek olan kÄ±sÄ±m LoadFromStream ve SaveToStream metodlarÄ±dÄ±r. Bu metodlarÄ±n iÃ§eriÄŸini kendinize gÃ¶re yeniden oluÅŸturmalÄ±sÄ±nÄ±z.</p><pre> </pre></p><h1>Resource Verilerini Okuyup Yazmak</h1><p
align="justify">Resoruce verileri, kÄ±saca aÃ§Ä±klamak gerekirse, exe ya da dll dosyanÄ±z iÃ§ine gÃ¶mÃ¼len verilerdir. Bu veriler resim, yazÄ±, icon, form olabileceÄŸi gibi herhangibir formatta stream verisi de olabilir.</p><p
align="justify">Resource dosyalarÄ± &quot;.RC&quot; uzantÄ±lÄ± bir dosyadan herhangi bir resource compiler ile derlenir. Bu derleme sonucunda &quot;.RES&quot; uzantÄ±lÄ± bir dosya oluÅŸacaktÄ±r. RES dosyalarÄ±nÄ± istediÄŸiniz bir resource derleyicisi ile oluÅŸturabilirsiniz. &Ccedil;Ã¼nkÃ¼ bu res dosyalarÄ± derleyiciden baÄŸÄ±msÄ±zdÄ±r. Fakat RC dosyasÄ±nÄ±n grameri deÄŸiÅŸiklik gÃ¶sterebilmektedir. Biz bu makalede resource verilerini derlemek iÃ§in delphi ile beraber gelen brcc32 derleyicisini kullanacaÄŸÄ±z. Ä°sterseniz Visual Studio veya benzeri bir baÅŸka resource manager ile RES dosyalarÄ± oluÅŸturabilirsiniz. EÄŸer Delphi 2009&#8242;a sahip iseniz, yeni &quot;Resource Manager&quot; ile daha rahat resource dosyalarÄ± oluÅŸturabilirsiniz.</p><p
align="center"><img
width="502" height="331" align="middle" alt="Delphi 2009 - Resource Manager" src="/wp-content/uploads/Image/post99/d2009_resource_manager.jpg" /> <font
size="1"> Delphi 2009&#8242;da menÃ¼den Project/Resources&#8230; altÄ±ndan ulaÅŸabilrsiniz.</font></p><p
align="justify">Biz elimizde Delphi&#8217;den baÅŸka bir ÅŸey olmadÄ±ÄŸÄ±nÄ± dÃ¼ÅŸÃ¼nerek iÅŸe koyulalÄ±m ve resource dosyamÄ±zÄ± oluÅŸturalÄ±m.</p><p
align="justify">Notepad ile yeni bir yazÄ± dosyasÄ± oluÅŸturalÄ±m ve iÃ§ine bir yerlerden uzun bir paragraf bulup yapÄ±ÅŸtÄ±rÄ±lÄ±m. Bunu yazi.txt ismi ile kaydelim. AynÄ± klasÃ¶re baÅŸka bir yazÄ± dosyasÄ± daha oluÅŸturalÄ±m ve iÃ§ine aÅŸaÄŸÄ±dakileri yazalÄ±m:</p><pre>yazi RCDATA yazi.txt </pre><p
align="justify">Daha sonra bu dosyayÄ± &quot;yazi.rc&quot; ismi ile aynÄ± klasÃ¶re kaydedelim.</p><p
align="justify">Burada ilk yazdÄ±ÄŸÄ±mÄ±z kelime resource&#8217;a verdiÄŸmiz isimdir. Ä°leride bu isme gÃ¶re resource verimizi kullanacaÄŸÄ±z. Ä°kinci kÄ±sÄ±mda RCDATA ile verimizin tipini belirledik. Burada RCDATA&#8217;nÄ±n dÄ±ÅŸÄ±nda BITMAP, CURSOR ve ICON gibi ayrÄ± ayrÄ± tipler kullanÄ±labilir. BunlarÄ±n tam listesi iÃ§in internette araÅŸtÄ±rma yapabilirsiniz. (<a
target="_blank" href="http://msdn.microsoft.com/en-us/library/aa381043(VS.85).aspx">http://msdn.microsoft.com/en-us/library/aa381043(VS.85).aspx</a>). En sondaki kÄ±sÄ±m ise resource olarak kullanacaÄŸÄ±mÄ±z verimizin dosyasÄ±nÄ± giriyoruz.</p><p
align="justify">BaÅŸlat/&Ccedil;alÄ±ÅŸtÄ±r ile cmd yazÄ±p entere basÄ±p komut satÄ±rÄ±na geÃ§elim. Buradan dosyalarÄ± kaydettiÄŸimiz klasÃ¶re geÃ§elim(msdos biliyorsunuzdur herhalde <img
src='http://www.diyezon.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ). ArdÄ±ndan aÅŸaÄŸÄ±daki komutu yazÄ±p entere basalÄ±m.</p><pre>brcc32 yazi.rc</pre><p
align="justify">Bir problem oluÅŸmadÄ± ise aynÄ± klasÃ¶rede yazi.res isimli bir dosya gÃ¶receÄŸiz.</p><p
align="justify">Bu iÅŸlemlerden sonra Delphi&#8217;ye geÃ§ip yeni bir uygulama aÃ§alÄ±m. Yeni uygulamamÄ±zÄ± .res dosyalarÄ±nÄ± oluÅŸturduÄŸumuz klasÃ¶re kaydedelim. Åžimdi az Ã¶nce oluÅŸturduÄŸumuz res dosyasÄ±nÄ± programÄ±mÄ±z iÃ§ine gÃ¶mmek iÃ§in gerekli iÅŸlemleri yapalÄ±m.</p><p
align="justify">Unit1&#8242;in kodlarÄ±nÄ± aÃ§alÄ±m ve uygun bir boÅŸluÄŸa aÅŸaÄŸÄ±daki derleyici direktifini girelim:</p><pre>
<pre class="brush: delphi">{$R yazi.res}</pre></pre><p
align="justify">ProgramÄ±zÄ± derlediÄŸimizde bu res dosyasÄ±nda buluna bÃ¼tÃ¼n veriler, resource verisi olarak programÄ±mÄ±za gÃ¶mÃ¼lecektir. Ä°sterseniz bunu ResHack gibi herhangi bir resource yÃ¶neticisi ile kontrol edebilirsiniz.</p><p
align="justify">Åžimdi bu gÃ¶mÃ¼lmÃ¼ÅŸ olan veriyi okumamÄ±z gerekiyor diyelim. Mesela az Ã¶nce programÄ±mÄ±z iÃ§ine gÃ¶mdÃ¼ÄŸÃ¼mÃ¼z yazi.txt dosyasÄ±nÄ± bir memo iÃ§ine alalÄ±m ve gÃ¶sterelim.</p><p
align="justify">Form Ã¼zerine bir adet memo bileÅŸeni ve bir adet button ekleyelim. Button&#8217;unun OnClick olayÄ±na ÅŸunlarÄ± yazalÄ±m:</p><pre>
<pre class="brush: delphi">var
  Res: TResourceStream;
begin
  Res := TResourceStream.Create(hInstance, &#039;yazi&#039;, RT_RCDATA);
  Memo1.Lines.LoadFromStream(Res);
end;</pre></pre><p
align="justify">ProgramÄ± Ã§alÄ±ÅŸtÄ±rÄ±p button&#8217;a basalÄ±m. Bir sorun Ã§Ä±kmadÄ± ise memo bileÅŸeninde yazi.txt dosyasÄ±ndaki yazÄ±lÄ± olan paragrafÄ± gÃ¶receÄŸiz.</p><p
align="justify">Bu yaptÄ±ÄŸÄ±mÄ±z Ã¶rnek ile gÃ¶rÃ¼yoruz ki; bir TResourceStream nesnesi, herhangi bir exe veya dll iÃ§indeki resource verilerine eriÅŸebiliyor. Create oluÅŸturucusunda gÃ¶rdÃ¼ÄŸÃ¼mÃ¼z ilk parametre resource verisini nereden Ã§ekeceÄŸimizi belirliyor. Buna daha sonra deÄŸineceÄŸiz. Ä°kinci parametre olarak eriÅŸeceÄŸimiz resource verisinin ismidir. Bunu RC dosyasÄ±nÄ± hazÄ±rlarken gÃ¶rmÃ¼ÅŸtÃ¼k. AynÄ± ÅŸekilde son parametre de RC dosyasÄ±nda belirlenmiÅŸti. Bu son parametre ile resource verisinin tipini belirliyoruz. Tek fark olarak baÅŸ tarafÄ±na RT_ Ã¶n ekini getiriyoruz.</p><p
align="justify">Sonraki iÅŸlem ise memo bileÅŸenin Lines Ã¶zelliÄŸine streamdeki veriyi aktarÄ±yoruz.</p><p
align="justify">Bu mantÄ±ÄŸÄ± kullanarak istediÄŸiniz tÃ¼rde veriyi resource olarak gÃ¶mebilir ve program Ã§alÄ±ÅŸmasÄ± anÄ±nda kullanabilirsiniz. Bu yaptÄ±ÄŸÄ±mÄ±z Ã¶rnek sadece mevcut programdan verileri Ã§ekebilir. Fakat baÅŸka bir dll ya da exe&#8217;den veri Ã§ekmemiz gerektiÄŸinde ne yapacaÄŸÄ±z?</p><p
align="justify">Ä°ÅŸte bu durumda hInstance olarak girdiÄŸimiz parametre deÄŸiÅŸecektir. &Ccedil;Ã¼nkÃ¼ burada girdiÄŸimiz parametre veriyi nereden Ã§ekeceÄŸimizi daha doÄŸrusu resource verisinini nerede olduÄŸunu belirler.</p><p
align="justify">Her program(exe, dll, ocx, ..) Ã§alÄ±ÅŸtÄ±rÄ±ldÄ±ÄŸÄ±nda windows tarafÄ±ndan bir handle numarasÄ± ile iliÅŸkilendirilir. Delphi&#8217;de bu handle numarasÄ±na eriÅŸebilmek iÃ§in hInstance isimli global bir deÄŸiÅŸkeni kullanÄ±yoruz. Bu yÃ¼zden Create oluÅŸturucusunda mevcut Ã§alÄ±ÅŸan programÄ±mÄ±zÄ±n handle numarasÄ±nÄ± buraya birinci parametre olarak girdik.</p><p
align="justify">Peki baÅŸka bir exe veya bir dll&#8217;in handle numarasÄ±nÄ± nasÄ±l alÄ±rÄ±z?</p><p
align="justify">Bunun iÃ§in cevabÄ±mÄ±z LoadLibrary fonksiyonudur. Bu fonksiyon ile Ã§aÄŸÄ±rdÄ±ÄŸÄ±mÄ±z herhangi bir program geÃ§ici olarak hafÄ±zaya yÃ¼klenir ve windows tarafÄ±ndan bir handle atanÄ±r. Bu handle numarasÄ± ise Ã§Ä±kÄ±ÅŸ olarak dÃ¶ner. EÄŸer yÃ¼kleme iÅŸlemi baÅŸarÄ±sÄ±z ise handle numarasÄ± 0 olarak dÃ¶necektir. Mesela yukarÄ±da yaptÄ±ÄŸÄ±mÄ±z iÅŸlemleri bir dll iÃ§inden almaya kalkarsak nasÄ±l yapacaktÄ±k?</p><pre>
<pre class="brush: delphi">var
  Res: TResourceStream;
  DLLHandle: THandle;
begin
  DLLHandle := LoadLibrary(&#039;resource.dll&#039;);
  if DLLHandle &lt;&gt; 0 then
  begin
    Res := TResourceStream.Create(DLLHandle, &#039;yazi&#039;, RT_RCDATA);
    Memo1.Lines.LoadFromStream(Res);
  end;
end;</pre></pre><p
align="justify">AynÄ± iÅŸlemi exe, ocx gibi diÄŸer Ã§alÄ±ÅŸtÄ±rÄ±labilir formatlar iÃ§inde yapabilirsiniz.</p><p
align="justify">ArtÄ±k herhangi bir veriyi exe iÃ§ine gÃ¶mÃ¼p okumayÄ± Ã¶ÄŸrendik. Åžimdi de bu iÅŸlemin bir benzerini veritabanlarÄ±nda yapalÄ±m.</p></p><h1>VeritabanÄ±nda Stream KullanÄ±mÄ±</h1><p
align="justify">ArtÄ±k buraya kadar Ã¶ÄŸrendiklerimizle herhangi bir stream verisini okuyup yazabiliriz. Burada yapacaÄŸÄ±mÄ±z iÅŸlem de pek farklÄ± olmayacak. Bu yÃ¼zden hemen konuya girelim ve kÄ±saca veritabanlarÄ±nda nasÄ±l stream kullanÄ±ldÄ±ÄŸÄ±nÄ± gÃ¶relim.</p><p
align="justify">VeritabanlarÄ±nda bulunan tablolarda stream verilerini saklamak iÃ§in alanÄ±mÄ±z BLOB tipinde olmalÄ±dÄ±r. BLOB tipindeki alanlar binary veriler tutabilir. Fakat indeksli ve Ã¼zerinde Ã§ok arama tarama iÅŸlemleri yapÄ±lan bir tablomuz var ise bu BLOB alanlar veritabanÄ± iÅŸlemlerini yavaÅŸlatacaktÄ±r. Bu yÃ¼zden bu BLOB alanlarÄ± baÅŸka bir tablo Ã¼zerine taÅŸÄ±mak performansÄ± artÄ±racaktÄ±r.</p><p
align="justify">Tabloda bulunan bir BLOB alana veri yazmak ve bu alandan veri okumak iÃ§in TBlobStream nesneleri kullanÄ±lÄ±r. KullanÄ±mÄ± aÅŸaÄŸÄ±daki gibidir:</p><pre>
<pre class="brush: delphi">
var
  blob: TBlobStream;
begin
  blob := tblBirTablo.CreateBlobStream(tblBirTablo.FieldByName(&#039;BlobAlan&#039;), bmReadWrite);
  try
    blob.Position := 0;
    blob.ReadBuffer(...);
    blob.WriteBuffer(...);
    ......
  finally
    blob.Free;
  end;
end;
</pre></pre><p
align="justify">Genel manada kullanÄ±m bu ÅŸekildedir fakat daha baÅŸka yÃ¶ntemler ile de blob stream oluÅŸturulabilir. Bu Ã¶rnekte BlobAlan isimli bir alan hem okuma hem de yazma iÅŸlemleri iÃ§in stream olarak bizim blob stream nesnemize atanmÄ±ÅŸtÄ±r. Burada sadece okuma iÅŸlemleri yapacaksak bmRead, sadece yazma iÅŸlemi yapacaksak bmWrite parametrelerini kullanmalÄ±yÄ±z.</p><h1>TStream&#8217;i .NET ve Delphi 2009&#8242;da Kullanmak</h1><p
align="justify">TStream sÄ±nÄ±fÄ± Delphi&#8217;nin bileÅŸen mantÄ±ÄŸÄ±nÄ±n temelini oluÅŸturmaktadÄ±r. Delphi, .NET ortamÄ±na taÅŸÄ±nÄ±rÄ±ken haliyle TStream sÄ±nÄ±fÄ± da ufak farklÄ±lÄ±klar ile .NET ortamÄ±na taÅŸÄ±nmÄ±ÅŸtÄ±r. Benim burada bahsedeceÄŸim konu sadece bu kÃ¼Ã§Ã¼k farklÄ±lÄ±klar olacaktÄ±r. Geri kalan iÅŸlemlerde buraya kadar Ã¶ÄŸrendiÄŸiniz bilgiler fazlasÄ±yla yetecektir.</p><p
align="justify">.NET ortamÄ±nda Pointer iÅŸlemleri kullanÄ±lmadÄ±ÄŸÄ±ndan TStream sÄ±nÄ±fÄ± ve alt sÄ±nÄ±flarÄ± iÃ§in bir deÄŸiÅŸikliÄŸe gidilmesi ÅŸarttÄ±. Bu yÃ¼zden, TStream sÄ±nÄ±fÄ± .NET ortamÄ±na taÅŸÄ±ndÄ±ÄŸÄ±nda Pointer iÅŸlemleri yerine, bu iÅŸlemlerin yerini tutan belirgin ve basit tipler iÃ§in ayrÄ± ayrÄ± metodlar hazÄ±rlandÄ±.</p><p
align="justify">Mesela hatÄ±rlarsanÄ±z normalde TStream sÄ±nÄ±fÄ±nda bulunan ReadBuffer ile bir srting veri yazdÄ±ÄŸÄ±mÄ±zda string&#8217;i pointer olarak type cast yapÄ±p parametre olarak giriyorduk. .NET&#8217;de pointer kullanmadÄ±ÄŸÄ±mÄ±z iÃ§in ReadBuffer yerine artÄ±k aynÄ± isimli ve sadece Ã¶zel tipler iÃ§in Ã¶zdeÅŸleÅŸtirilmiÅŸ bir metodumuz var. Bu metodu kullanarak rahat bir ÅŸekilde pointer kullanmadan iÅŸlemlerimizi aynÄ± ÅŸekilde yapabiliriz. Tabi bu daha Ã¶nce yaptÄ±ÄŸÄ±mÄ±z Win32 TStream sÄ±nÄ±fÄ±na gÃ¶re Ã§ok rahatlÄ±k getirmektedir. Bu da hiÃ§ ÅŸÃ¼phesiz .Net&#8217;in getiridiÄŸi rahatlÄ±klardan birisi.</p><p
align="justify">ReadBuffer ver WriteBuffer metodlarÄ±ndan bir kaÃ§Ä±ndaki deÄŸiÅŸlikliklere gÃ¶z atalÄ±m:</p><pre>
<pre class="brush: delphi">
    //TBytes
    procedure ReadBuffer(Buffer: TBytes; Count: Longint); overload;
    procedure WriteBuffer(const Buffer: TBytes; Count: Longint); overload;

    //Boolean
    procedure ReadBuffer(var Buffer: Boolean); overload;
    procedure WriteBuffer(const Buffer: Boolean); overload;

    //Integer
    procedure ReadBuffer(var Buffer: Integer); overload;
    procedure WriteBuffer(const Buffer: Integer); overload;
    procedure WriteBuffer(const Buffer: Integer; Count: Longint); overload; platform;

    //Char
    procedure ReadBuffer(var Buffer: Char); overload;
    procedure ReadBuffer(var Buffer: Char; Count: Longint); overload; platform;
    procedure WriteBuffer(const Buffer: Char); overload;
    procedure WriteBuffer(const Buffer: Char; Count: Longint); overload; platform;

    // AnsiChar
    procedure ReadBuffer(var Buffer: AnsiChar); overload;
    procedure ReadBuffer(var Buffer: AnsiChar; Count: Longint); overload; platform;
    procedure WriteBuffer(const Buffer: AnsiChar); overload;
    procedure WriteBuffer(const Buffer: AnsiChar; Count: Longint); overload; platform;
</pre></pre><p
align="justify">Tam liste iÃ§in lÃ¼tfen Borland.Vcl.Classes unitinde bulunan TStream sÄ±nÄ±fÄ±na ya da yardÄ±ma gÃ¶z atÄ±nÄ±z.</p><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi aynÄ± ReadBuffer metodu, overload yÃ¶ntemi ile bir Ã§ok kez tanÄ±mlanmÄ±ÅŸ. Biz bunlardan ihtiyacÄ±mÄ±z olanÄ± seÃ§ip kullanacaÄŸÄ±z. Boolean ve Integer yazÄ±mÄ± iÃ§in tek bir adet parametre gerektirdiÄŸine dikkat ediniz.</p><p
align="justify">Diyelimki stream Ã¼zerine yazdÄ±racaÄŸÄ±mÄ±z veya okuyacaÄŸÄ±mÄ±z veri Ã§eÅŸidine uygun bir metod bulunmamakta. Bu durumda verimizi bir byte dizisi gibi dÃ¼ÅŸÃ¼nÃ¼p ona gÃ¶re davranacaÄŸÄ±z. Bu durumda verimizi TBytes&#8217;a yani &quot;array of Byte&quot; tipinieÃ§evirmemiz gerekmektedir. Bunun iÃ§in herhangi bir for dÃ¶ngÃ¼sÃ¼ tanÄ±mlayarak bu iÅŸlememizi yapabiliriz.</p><p
align="justify">Integter ile ilgili metodlara bakarsanÄ±z, en sonda fazladan Count parametresi alan bir metod yerleÅŸtirdim. BÃ¼tÃ¼n metod Ã§eÅŸitlerinde alternatif olarak bu ikininci parametreye sahip olan metodlar mevcuttur. Bu parametreyi mesela Integer iÃ§in normalde 4 byte ayrÄ±lmasÄ±na raÄŸmen siz 10 byte yer ayÄ±rmak istediÄŸinizde kullanablirsiniz.</p><p
align="justify">Bu metodlara baktÄ±ÄŸÄ±nÄ±zda string ile ilgili bir Ã¶zel metodun olmadÄ±ÄŸÄ±nÄ± farkedeceksiniz. Peki string veriyi nasÄ±l yazacaÄŸÄ±z?</p><p
align="justify">Bu durumda veriyi hangi encode&#8217;da yazacaÄŸÄ±mÄ±z veya okuyacaÄŸÄ±mÄ±z Ã¶nemli. Veriyi istersek UTF8 formatÄ±nda istersek UTF16 veya ANSI olarak okuyabilir ve yazabiliriz. Bu durumda string verimizi byte dizisine Ã§eviren veya byte dizisini string verisine Ã§eviren bir yÃ¶nteme ihtiyacÄ±mÄ±z var. AÅŸaÄŸÄ±daki Ã¶rneÄŸe gÃ¶z atalÄ±m:</p><pre>
<pre class="brush: delphi">var
  Mem: TMemoryStream;
  s: string;
  bytes: TBytes;
begin
  Mem := TMemoryStream.Create;
  try
    s := &#039;diyezon&#039;;
    bytes := Encoding.UTF8.GetBytes(s); //uses&#039;a System.Text eklenmeli
    Mem.WriteBuffer(bytes, Length(bytes));
    Mem.Position := 0;
    Memo1.Lines.LoadFromStream(Mem);
  finally
    Mem.Free; //YapmanÄ±za gerek yok.
  end;
end;</pre></pre><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi string verimizi utf-8 olarak stream Ã¼zerine attÄ±k ardÄ±ndan memo1 ile ekranda gÃ¶sterdik. Bu iÅŸlemi yapabilmek iÃ§in string verisini uygun bir byte dizisine Ã§evirmemiz gerkiyordu. Bunun iÃ§in System.Text alanÄ±nda bulunan Encoding sÄ±nÄ±fÄ±nÄ± kullanÄ±yoruz. Bu sÄ±nÄ±fÄ± kullanabilmek iÃ§in uses&#8217;a System.Text&#8217;i eklemelisiniz.</p><p
align="justify">Ä°sterseniz bu yazma iÅŸlemini Encoding.Unicode ile utf-16 ya da diÄŸer adÄ±yla unicode olarak, isterseniz Encoding.Default ile iÅŸletim sisteminin varsayÄ±lan ansi karakterleri olarak yazÄ±p okuyabiliriz. Ã–nemli olan string bir ÅŸekilde byte dizisine Ã§evrilmiÅŸ olmasÄ± gerekmektedir. AyrÄ±ca yazma ve okuma iÅŸlemlerinde aynÄ± tip encode formatÄ±nÄ± kullandÄ±ÄŸÄ±nÄ±zdan emin olun. Yani ya her ikisinde de Unicode ya da her ikisinde de UTF8 kullanÄ±n.</p><p
align="justify">EÄŸer TBytes&#8217;dan stringe Ã§evirim yapmamÄ±z gerekirse bu durumda aÅŸaÄŸÄ±daki metodu kullanÄ±yoruz:</p><pre>
<pre class="brush: delphi">s := Encoding.UTF8.GetString(bytes)</pre></pre><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi .net ile bu iÅŸlemleri yapmak Ã§ok basit. AyrÄ±ca en sonda stream&#8217;i free yapmasanÄ±z da Garbage Collector sizin iÃ§in bunu yapacaktÄ±r. Fakat TFileStream kullanÄ±yor ve dosyaya fmShareExclusive gibi kilitleyici bir parametre ile ulaÅŸÄ±yorsanÄ±z, stream nesnesini Ã¶ldÃ¼rmeden veya program kapanmadan, baÅŸka bir program dosyaya ulaÅŸamaz, dosya kilitli kalÄ±r.</p><p
align="justify">Bu bÃ¶lÃ¼mde bahsetmek istediÄŸim baÅŸka bir konu da bu iÅŸlemleri Delphi 2009 ve Ã¼stÃ¼nde yapmak. Burada bahsediyorum, Ã§Ã¼nkÃ¼ bahsedeceÄŸimiz bu konu .net ile de ilgili bir konu.</p><p
align="justify">AslÄ±nda daha Ã¶nceden gÃ¶rdÃ¼k ki; bir stringi stream&#8217;e yazmak iÃ§in stream&#8217;in kaÃ§ karakter olduÄŸundan Ã§ok ,boyutunu bilmemiz gerekiyor. Bu yÃ¼zden ansi ya da ascii stringlerde boyut olarak her zaman Length(string) ÅŸeklinde aldÄ±k. &Ccedil;Ã¼nkÃ¼ ansi stringlerde boyut = karakter sayÄ±sÄ±dÄ±r. Fakat unicode olan stringlerde bu durum biraz farklÄ±dÄ±r. Unicode olan stringler 1 byte deÄŸil, 2 byte yer kaplarlar. Bu yÃ¼zden WideString gibi unicode stringler ile uÄŸraÅŸtÄ±ÄŸÄ±mÄ±zda artÄ±k boyutumuz Length*2 olmaktadÄ±r. BildiÄŸiniz gibi Delphi.Net ve Delphi 2009 ve yukarÄ±sÄ± derleyicilerde &quot;string&quot; ve &quot;Char&quot; tipi unicode formatÄ±ndadÄ±r. Bu derleyicilerde ansi olarak veri tanÄ±mlamamÄ±z gerektiÄŸinde AnsiString, AnsiChar, PAnsiChar gibi tipleri kullanmalÄ±yÄ±z. Aksi durumda bu derleyicilerde bir Char tipi 2 byte yer kaplar. Bu konu ile ilgili daha Ã¶nceden Ã¶rnek verdiÄŸimizden bu konuyu burada bitiriyorum.</p></p><h1>.NET Stream Nesnesinin KullanÄ±mÄ±</h1><p
align="justify">TStream&#8217;e ek olarak, .net&#8217;de aynÄ± mekanizma bulunmaktadÄ±r. Neden bilmiyorum ama .net&#8217;de bulununa bir Ã§ok teknoloji Delphi ile benzerlik gÃ¶stermektedir. Belki de c# ve .net&#8217;in fikir babasÄ± olan Anders Hejlsberg&#8217;in delphi&#8217;nin ilk temellerini atmasÄ±ndan kaynaklanÄ±yor olabilir. Her neyse biz konumuza dÃ¶nelim.</p><p
align="justify">AslÄ±nda bu konu Ã§ok uzun anlatÄ±labilecek bir konu ve burada bahsetmemiz makaleyi bir Ã¼Ã§Ã¼ncÃ¼ bÃ¶lÃ¼me bile taÅŸÄ±yabilir. Ki bence buna gerek yok. Ben sadece TStream ile arasÄ±ndaki benzerlikleri gÃ¶sterip, nasÄ±l kullanÄ±ldÄ±ÄŸÄ±na dair bir Ã¶rnek vermek istiyorum.</p><p
align="justify">Bu bÃ¶lÃ¼mÃ¼ VCL.Net kullanmak istemeyip saf .net kodu oluÅŸturmak isteyenler veya Delphi Prism kullananlar iÃ§in yazmak istedim. Aksi takdirde TStream sÄ±nÄ±fÄ± Ã§oÄŸu kez iÅŸimizi rahat bir ÅŸekilde gÃ¶rmektedir. Fakat bazen kullandÄ±ÄŸÄ±mÄ±z .net sÄ±nÄ±flarÄ± .net&#8217;in stream sÄ±nÄ±flarÄ±na ihtiyaÃ§ duyabilmektedir.</p><p
align="justify">VCL&#8217;de bulunan bazÄ± stream sÄ±nÄ±flarÄ± yerine .net&#8217;de bulunan karÅŸÄ±lÄ±klarÄ±nÄ± ÅŸÃ¶yle sÄ±ralayabilriiz:</p><pre>TFileStream =&gt; FileStream
TMemoryStream =&gt; MemoryStream
TIdTCPClient =&gt; NetwrokStream</pre><p>vs..</p><p
align="justify">Tabi bu stream sÄ±nÄ±flarÄ±nÄ±n metodlarÄ± benzerlik gÃ¶sterse de kullanÄ±mlarÄ± farklÄ±dÄ±r. Bu stream sÄ±nÄ±flarÄ±nÄ± kullanabilemek iÃ§in uses&#8217;a System.IO alanÄ±nÄ± eklemelisiniz. Biz buradan MemoryStream ile ilgili bir Ã¶rnek verelim:</p><pre>
<pre class="brush: delphi">var
  Mem: MemoryStream;
  s: string;
  bytes: array of Byte;
begin
  Mem := MemoryStream.Create;
  s := &#039;diyezon&#039;;
  bytes := Encoding.UTF8.GetBytes(s);
  Mem.Write(bytes, 0, Length(bytes));</pre></pre><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi kullanÄ±m olarak TStream&#8217;den farklÄ± deÄŸil. Fakat Write metodunu TStream&#8217;de olduÄŸu gibi bir Ã§ok Ã§eÅŸidi olduÄŸunu zannetmeyin sakÄ±n. &Ccedil;Ã¼nkÃ¼ MemoryStream sÄ±nÄ±fÄ±nda Write metodunun sadece iki adet varyasyonu mevcut. Bu metodda ilk parametre byte dizisi, ikinci parametre nereden itibaren yazÄ±lacaÄŸÄ± yani ofset ve Ã¼Ã§Ã¼ncÃ¼ parametre olarak yazdÄ±rÄ±lacak verinin uzunluÄŸu giriliyor.</p><p
align="justify">Bunun dÄ±ÅŸÄ±nda bu string ve binary deÄŸerleri rahat bir ÅŸekilde okuyup yazabilmek iÃ§in Ã§eÅŸitli ek sÄ±nÄ±flar kullanÄ±lmaktadÄ±r. Mesela BinaryWriter ile binary deÄŸerleri stream Ã¼zerine yazabiliriz veya StreamReader ile streamden karakter verilerini okuyabiliriz. AÅŸaÄŸÄ±daki Ã¶rneÄŸe gÃ¶z atalÄ±m:</p><pre>
<pre class="brush: delphi">var
  Mem: MemoryStream;
  textW: StreamWriter;
  s: string;
  bytes: array of Byte;
begin
  Mem := MemoryStream.Create;
  textW := StreamWriter.Create(Mem);
  s := &#039;diyezon&#039;;
  textW.Write(s);</pre></pre><p
align="justify">YukarÄ±da yaptÄ±ÄŸÄ±mÄ±z iÅŸlemin aynÄ±sÄ±nÄ± burada StreamWriter sÄ±nÄ±fÄ± ile gerÃ§ekleÅŸtirdik. Ä°ÅŸte burada StreamWriter sÄ±nÄ±fÄ±nÄ±n Write metodunda bir Ã§ok varyasyon mevcuttur. Bu varyasyonlara yardÄ±m dosyalarÄ±ndan ulaÅŸabilirsiniz. Mesela bir Integer deÄŸer yazmak iÃ§in yine StreamWriter&#8217;a ait Write metodunu kullanmamÄ±z kafidir.</p><p
align="justify">Bunun dÄ±ÅŸÄ±nda bir de kullanabileceÄŸimiz BinaryWriter ve BinaryRead sÄ±nÄ±flarÄ± mevcuttur. Bu sÄ±nÄ±flar ise binary verileri okuyup yazmak iÃ§in kullanÄ±lÄ±rlar. Ama kullanÄ±m aynÄ± olduÄŸu iÃ§in bu konuya da girmeyeceÄŸim.</p><p
align="justify">Burada en son olarak BufferedStream sÄ±nÄ±fÄ±ndan bahsetmek istiyorum. Bu stream ile okuma ve yazma iÅŸlemlerini baÅŸka bir stream Ã¼zerinde buffer&#8217;layarak daha hÄ±zlÄ± iÅŸlemler yaptÄ±rabilirsiniz. HatÄ±rlarsanÄ±z TMemoryStream sÄ±nÄ±fÄ±ndan bahsederken, bu sÄ±nÄ±fÄ± diÄŸer stream sÄ±nÄ±flardaki okuma yazma iÅŸlemleri yerine kullanÄ±labileceÄŸinden ve bunun performansÄ± artÄ±rdÄ±ÄŸÄ±ndan bahsetmiÅŸtik. Ä°ÅŸte burada TMemoryStream bir buffer vazifesi gÃ¶rmektedir.</p><p
align="justify">Mesela bir dosyaya bir Ã§ok veri yazÄ±lacak, ve bu veriler parÃ§a parÃ§a yazÄ±lacak. AyrÄ±ca bu dosya stream&#8217;i Ã¼zerinde bir Ã§ok seek iÅŸlemi yani ileri geri alma iÅŸlemleri yapÄ±lacak. Ä°ÅŸte bu durumda direk olarak TFileStream gibi bir dosya stream nesnesi ile uÄŸraÅŸmak yerine hafÄ±za stream&#8217;leri ile uÄŸraÅŸmamÄ±z iÅŸlemlerimizin performansÄ±nÄ± Ã¶nemli derecede artÄ±racaktÄ±r. YapacaÄŸÄ±mÄ±z stream iÅŸlemlerini bir hafÄ±za stream&#8217;i Ã¼zerinde gerÃ§ekleÅŸtirip, en son iÅŸlemimiz bittiÄŸinde hafÄ±za stream&#8217;ini ilgili stream nesnesine aktarmak en akÄ±llÄ±ca yÃ¶ntemdir. Ä°ÅŸte bu yÃ¶nteme buffering ya da tamponlama tekniÄŸi denir.</p><p
align="justify">Ä°ÅŸte bu anlattÄ±ÄŸÄ±mÄ±z tekniÄŸi BufferedStream nesnesi gerÃ§ekleÅŸtirmektedir. AynÄ± iÅŸlemi ekstra bir memory stream tanÄ±mlayarak siz de oluÅŸturabilirisiniz, hatta bu makalede buna benzer Ã¶rnekleri Ã§ok gÃ¶rdÃ¼k.</p><p
align="justify">BufferedStream sÄ±nÄ±fÄ±nÄ± kullanmak isteyenler, yardÄ±m dosyalarÄ±nda ve msdn&#8217;de tanÄ±mlamasÄ±na bakabilirler. ArtÄ±k stream mantÄ±ÄŸÄ±nÄ± kafanÄ±zda yerleÅŸtirdiÄŸinize gÃ¶re burada kullanÄ±mÄ±nÄ± vermek artÄ±k sÄ±kacaktÄ±r.</p><h1>SonuÃ§</h1><p
align="justify">Bir makalenin daha sonuna geldik. Bu makale serisinde VCL ve .net&#8217;de kullanÄ±lan stream sÄ±nÄ±flarÄ±na deÄŸinmeye Ã§alÄ±ÅŸtÄ±k ve bu sÄ±nÄ±flarÄ±n kullanÄ±mÄ±na dair Ã§eÅŸitli Ã¶rnekler vermeye Ã§alÄ±ÅŸtÄ±k.</p><p
align="justify">Tabi ki burada verdiklerimiz stream iÃ§in en temel konulardÄ±r. Bu makaleyi okuduktan sonra artÄ±k kafanÄ±zda stream&#8217;e ait somut dÃ¼ÅŸÃ¼ncelerin oluÅŸtuÄŸunu zannediyorum. Ve bundan sonra Ã¶nÃ¼nÃ¼ze gelecek olan bir Ã§ok stream iÅŸlemini rahat bir ÅŸekilde halledebileceÄŸinizi umut ediyorum.</p><p
align="justify">Fikir, eleÅŸtiri ve yorumlarÄ±nÄ±zÄ± bekliyorum. AyrÄ±ca makaledeki hatalarÄ± bildirirseniz sevinirim.</p><p>HayÄ±rlÄ± Ã§alÄ±ÅŸmalar.</p><p
align="center"><strong>Fatih Tolga ATA, Åžubat 2009</strong></p></p></p> ]]></content:encoded> <wfw:commentRss>http://www.diyezon.com/streamde-uzmanlasalim-bolum-2/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Stream&#8217;de UzmanlaÅŸalÄ±m&#8230; (BÃ¶lÃ¼m 1)</title><link>http://www.diyezon.com/streamde-uzmanlasalim-bolum-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=streamde-uzmanlasalim-bolum-1</link> <comments>http://www.diyezon.com/streamde-uzmanlasalim-bolum-1/#comments</comments> <pubDate>Sat, 13 Sep 2008 07:15:49 +0000</pubDate> <dc:creator>Fatih Tolga Ata</dc:creator> <category><![CDATA[Delphi]]></category> <category><![CDATA[stream]]></category> <category><![CDATA[TBlobStream]]></category> <category><![CDATA[TFileStream]]></category> <category><![CDATA[TMemoryStream]]></category> <category><![CDATA[TResourceStream]]></category> <category><![CDATA[TStream]]></category><guid
isPermaLink="false">http://www.diyezon.com/?p=62</guid> <description><![CDATA[Diyezon&#8217;a yazmayalÄ± baya bir sÃ¼re olmuÅŸtu. Neredeyse diyezon, kendi iÅŸlerim yÃ¼zÃ¼nden hayalet site olma yolunda ilerliyordu. Bundan Ã¶nceki son yazÄ±mÄ± yaklaÅŸÄ±k bir sene Ã¶nce yayÄ±nlamÄ±ÅŸtÄ±m. Her neyse&#8230; Stream&#8217;ler hakkÄ±nda bir makale yazmak, yapacaklarÄ±m arasÄ±ndaydÄ±. En son gelen bir istek Ã¼zerine stream konusuna el atalÄ±m istedim. Bu makale serimizde hem VCL&#8217;de bulunan TStream, hem de .NET&#8217;de [...]]]></description> <content:encoded><![CDATA[<p
align="justify">Diyezon&#8217;a yazmayalÄ± baya bir sÃ¼re olmuÅŸtu. Neredeyse diyezon, kendi iÅŸlerim yÃ¼zÃ¼nden hayalet site olma yolunda ilerliyordu. Bundan Ã¶nceki son yazÄ±mÄ± yaklaÅŸÄ±k bir sene Ã¶nce yayÄ±nlamÄ±ÅŸtÄ±m. Her neyse&#8230;</p><p
align="justify">Stream&#8217;ler hakkÄ±nda bir makale yazmak, yapacaklarÄ±m arasÄ±ndaydÄ±. En son gelen bir istek Ã¼zerine stream konusuna el atalÄ±m istedim. Bu makale serimizde hem VCL&#8217;de bulunan TStream, hem de .NET&#8217;de bulunan Stream sÄ±nÄ±flarÄ± ve kullanÄ±mlarÄ±ndan bahsetmeye Ã§alÄ±ÅŸacaÄŸÄ±m.</p><p
align="justify">Ã–zellikle TStream Ã¼zerinde stringlerle uÄŸraÅŸmak gibi bir Ã§ok konu programcÄ±larÄ±n kafasÄ±nÄ± karÄ±ÅŸtÄ±rabilmektedir. Bu ve bunun gibi sorunlarÄ±n Ã§Ã¶zÃ¼mlerine de Ã§areler bulmaya Ã§alÄ±ÅŸacaÄŸÄ±z.</p><p><span
id="more-62"></span></p><h1>Stream Nedir?</h1><p
align="justify">Bilgisayar ortamÄ±nda yazma-okuma iÅŸlemlerinden bahsettiÄŸimizde aklÄ±mÄ±za bir Ã§ok ÅŸey gelir. Mesela disk Ã¼zerinde bir dosyaya eriÅŸip Ã¼zerinde yazma ve okuma iÅŸlemleri yapabiliriz. Veya bir hafÄ±za bÃ¶lgesinde yazma-okuma iÅŸlemleri yapabileceÄŸimiz gibi bir veritabanÄ±ndaki bir tablo alanÄ±nda veya daha baÅŸka Ã§eÅŸit Ã§eÅŸit ortamlar Ã¼zerinde yazma-okuma iÅŸlemleri yapabiliriz. Bu bÃ¼tÃ¼n yazma-okuma iÅŸlemleri aslÄ±nda her zaman yÃ¶ntemi, iÅŸleyiÅŸi aynÄ± olan bir fonksiyonlar dizisidir. Sadece alt planda yazma-okuma iÅŸleminin yapÄ±lacaÄŸÄ± yÃ¼zeyde(disk, hafÄ±za&#8230;) farklÄ±lÄ±klar oluÅŸmaktadÄ±r.</p><p
align="justify">Ä°ÅŸte bu iÅŸlemleri kolay bir ÅŸekilde, ortak bir sÄ±nÄ±f Ã¼zerinden yapmak istediÄŸimiz zaman ortaya Stream gibi bir yapÄ± Ã§Ä±kÄ±yor. Stream nesnelerini kullanarak, bir dosyayÄ± yazÄ±p okuyabilir, aynÄ± fonksiyonlarÄ± kullanarak bir hafÄ±za bÃ¶lgesine ulaÅŸÄ±labilir veya yine aynÄ± fonksiyonlar ile bir veritabanÄ± tablosunun alanÄ±na ulaÅŸÄ±labilir.</p><p
align="justify">Stream, burada anlatÄ±lan basit Ã¶zelliklerin yanÄ±nda, stream verileri Ã¼zerinde bir Ã§ok iÅŸlemi yapabilmemize imkan saÄŸlamaktadÄ±r. Bu makalemizde bunlarÄ± ayrÄ±ntÄ±sÄ± ile gÃ¶rmeye Ã§alÄ±ÅŸacaÄŸÄ±z.</p><h2>Stream Verileri</h2><p
align="justify">Stream nesneleri, stream verilerini kullanmamÄ±zÄ± saÄŸlamaktadÄ±r. Stream verileri, Ã¼zerinde Ã§alÄ±ÅŸÄ±lan yere gÃ¶re Ã§eÅŸitli veriler iÃ§ermektedir. Bu bir resim dosyasÄ± olabileceÄŸi gibi kendimize Ã¶zel Ã§ok farklÄ± bir format da olabilir.</p><p
align="justify">Buradan da anlaÅŸÄ±lacaÄŸÄ± gibi, stream verileri bir nevi bir byte dizisidir. Yani aynÄ± veriyi &quot;<font
face="Courier New"><strong>array of</strong> byte</font>&quot; ÅŸeklinde kullanarak da oluÅŸturabilir ve Ã¼zerinde iÅŸlem yapabiliriz. Fakat bu, bize ek masraftan baÅŸka bir ÅŸeye yaramayacaktÄ±r. &Uuml;stelik yazacaÄŸÄ±mÄ±z fonksiyon ya da sÄ±nÄ±f stream nesneleri gib esnek ve hÄ±zlÄ± olmayacaktÄ±r.</p><h2>Stream Ne Zaman KullanÄ±lmalÄ±?</h2><p
align="justify">YapacaÄŸÄ±mÄ±z iÅŸlemerde stream mi, array mi kullanÄ±lmalÄ± noktasÄ±nda karar vermek istediÄŸimizde bir kaÃ§ hususu gÃ¶z Ã¶nÃ¼nde bulundurmamÄ±z gerekecektir.</p><p
align="justify">Ä°lk olarak bilmemiz gereken stream verileri array&#8217;de olduÄŸu gibi indeksli <strong>deÄŸildir</strong>. EÄŸer kullanacaÄŸÄ±mÄ±z veriler, sabit veri tipi ise ve bir for dÃ¶ngÃ¼sÃ¼ne girmek Ã¼zere oluÅŸturulacak ise kullanacaÄŸÄ±mÄ±z nesne array olacaktÄ±r. Stream&#8217;de de istediÄŸiniz veriye array&#8217;de olduÄŸu gibi ulaÅŸabilirsiniz. Fakat bu ileride de gÃ¶receÄŸimiz gibi array indekslerinden farklÄ± olarak Ã§alÄ±ÅŸmaktadÄ±r.</p><p
align="justify">EÄŸer bu veri dizimiz bir disk veya bir hafÄ±za bÃ¶lgesi Ã¼zerine yazÄ±lacaksa ve burada iÅŸlem yapÄ±lacaksa, bu durumda array yerine stream kullanÄ±lmasÄ± bize bir Ã§ok kolaylÄ±k sunacaktÄ±r.</p><p
align="justify">AynÄ± ÅŸekilde veri dizimiz sabit veri tipleri iÃ§ermiyorsa yani sadece <strong><font
face="Courier New">array of string</font></strong> veya sadece <font
face="Courier New"><strong>array of</strong> Integer</font> deÄŸilse bu durumda yine stream kullanmalÄ±yÄ±z. Mesela veri dizimizin birinci elemanÄ± 4 karakterlik bir <strong><font
face="Courier New">string</font></strong>, ikinci elmanÄ± bir <font
face="Courier New">Integer</font>, Ã¼Ã§Ã¼ncÃ¼ elemanÄ± bir <font
face="Courier New">Boolean</font>, vs&#8230; gibi. Bu ÅŸekilde kendi dosya formatÄ±mÄ±zÄ± oluÅŸturabileceÄŸimiz gibi, doc, exe, zip gibi bir Ã§ok binary dosyasÄ±nÄ±n yapÄ±sÄ±nÄ± bildiÄŸimizde bu dosyalarÄ±n verilerine de ulaÅŸabiliriz.</p><h1>VCL&#8217; de Stream KullanÄ±mÄ±</h1><p
align="justify">Ä°lk baÅŸta VCL ile stream kullanÄ±mÄ±na deÄŸinelim. ArdÄ±nda .Net Ã¼zerinde stream kullanÄ±mÄ±nÄ± gÃ¶receÄŸiz.</p><p
align="justify">VCL ile stream iÅŸlemleri yapabilmek iÃ§in <font
face="Courier New">TStream </font>sÄ±nÄ±fÄ±ndan tÃ¼reyen bir Ã§ok sÄ±nÄ±f mevcuttur. <font
face="Courier New">TStream </font>sÄ±nÄ±fÄ± <strong>abstract </strong>olarak tanÄ±mlanmÄ±ÅŸ bir sÄ±nÄ±ftÄ±r ve direk olarak kullanÄ±lamaz. Abstract olarak oluÅŸturulmuÅŸ olan bir sÄ±nÄ±ftan <strong>nesne oluÅŸturulamaz.</strong> Ancak bu abstract sÄ±nÄ±ftan tÃ¼remiÅŸ olan <strong>abstract olmayan sÄ±nÄ±flardan</strong> nesne oluÅŸturulabilir. Bu ÅŸekilde bir yapÄ± olmasÄ±, tÃ¼m stream sÄ±nÄ±flarÄ±nÄ±n aynÄ± olan bir Ã§ok metod ve Ã¶zelliÄŸe sahip olmasÄ±nÄ± saÄŸlar. Abstract sÄ±nÄ±flarÄ±n avantajlarÄ± burada anlatÄ±lacak kadar kÄ±sa deÄŸil. Bu yÃ¼zden ÅŸimdilik bu kadar bilmemiz yeterli.</p><p
align="justify">Help dosyasÄ±na gÃ¶z attÄ±ÄŸÄ±mÄ±zda <font
face="Courier New">TStream </font>sÄ±nÄ±fÄ±ndan tÃ¼remiÅŸ bir Ã§ok stream sÄ±nÄ±fÄ±nÄ± gÃ¶rÃ¼yoruz.</p><p
align="justify"><font
face="Courier New">TFileStream</font>: Disk yani <strong>dosya sistemi</strong> Ã¼zerinde bulunan dosyalarla iÅŸlem yapmamÄ±zÄ± saÄŸlar.</p><p
align="justify"><font
face="Courier New">TMemoryStream</font>: Dosyalar Ã¼zerinde yapÄ±lan aynÄ± iÅŸlemleri bir <strong>hafÄ±za bÃ¶lgesi</strong> Ã¼zerinde yapmamÄ±zÄ± saÄŸlar.</p><p
align="justify"><font
face="Courier New">TBlobStream</font>: VeritabanÄ±nda bulunan bir tablodaki <font
face="Courier New">BLOB</font> yani binary veri olarak tanÄ±mlanmÄ±ÅŸ alanlar Ã¼zerinde okuma-yazma iÅŸlemleri yapmamÄ±zÄ± saÄŸlar.</p><p
align="justify"><font
face="Courier New">TResourceStream</font>: Resource dediÄŸimiz, exe, dll gibi Ã§alÄ±ÅŸtÄ±rÄ±labilir dosyalar iÃ§ine gÃ¶mÃ¼lÃ¼ olan resim, yazÄ±, dialog kutularÄ±, versiyon bilgisi gibi Ã§ok Ã§eÅŸitli verileri okuyup yazmamÄ±za imkan saÄŸlamaktadÄ±r.</p><p
align="justify"><font
face="Courier New">TStringStream</font>: AynÄ± iÅŸlemleri bir string verisi Ã¼zerinde iÅŸlem yapabilmemizi saÄŸlar. BÃ¶ylece, sÄ±nÄ±rsÄ±z uzunlukta bir string Ã¼zerinde stream ile yapÄ±labilecek her tÃ¼rlÃ¼ iÅŸlemler yapÄ±labilir.</p><p
align="justify">Bunlar, temelde kullanÄ±lan stream Ã§eÅŸitleridir. Bunun gibi Ã¶zel olarak tasarlanmÄ±ÅŸ bir Ã§ok stream sÄ±nÄ±fÄ± da olabilir. Fakat hepsi TStream sÄ±nÄ±fÄ±ndan tÃ¼rediÄŸi iÃ§in, kullanÄ±mlarÄ± da aynÄ± olacaktÄ±r.</p><h1>Dosyalar &Uuml;zerinde Stream Ä°ÅŸlemleri</h1><p
align="justify">Dosyalar ile uÄŸraÅŸÄ±rken <font
face="Courier New">TFileStream </font>kullanÄ±ldÄ±ÄŸÄ±nÄ± sÃ¶ylemiÅŸtik. <font
face="Courier New">TStream </font>sÄ±nÄ±flarÄ±nÄ±n nasÄ±l kullanÄ±ldÄ±ÄŸÄ±nÄ±, sonucu kolay gÃ¶rme aÃ§Ä±sÄ±ndan ilk baÅŸta dosyalar Ã¼zerinde gÃ¶relim. Ä°leride diÄŸer stream Ã§eÅŸitlerine de deÄŸineceÄŸiz.</p><pre>
<pre class="brush: delphi">
var
  AFile: TFileStream;
  Buffer: String;
begin
  AFile := TFileStream.Create(&#039;C:\deneme.txt&#039;, fmCreate or fmShareDenyNone);
  try
    Buffer := &#039;Deneme&#039;;
    AFile.WriteBuffer(Pointer(Buffer)^, Length(Buffer));
  finally
    AFile.Free;
  end;
</pre></pre><p
align="justify">Bu kodlarÄ± bir button&#8217;nun <font
face="Courier New">OnClick </font>olayÄ±na yerleÅŸtirip deneyelim. Kodlar Ã§alÄ±ÅŸtÄ±rÄ±ldÄ±ÄŸÄ±nda, <font
face="Courier New">C: </font>Ã¼zerinde eÄŸer bir eriÅŸim ihlali yoksa <em>deneme.txt</em> isminde bir dosya gÃ¶receÄŸiz.</p><p
align="justify">Ä°lk bakÄ±ÅŸta bu kodlar Ã¼rkÃ¼tÃ¼cÃ¼ gelebilir. Fakat konular ilerledikÃ§e stream kullanmanÄ±n ne kadar rahat olduÄŸunu gÃ¶receÄŸiz.</p><p
align="justify"><font
face="Courier New">AFile</font>&#8216;Ä±n oluÅŸturulduÄŸu satÄ±ra bakalÄ±m. Bir <font
face="Courier New">TFileStream </font>nesnesi oluÅŸturabilmeniz iÃ§in iki adet parametreye ihtiyacÄ±nÄ±z var. Birincisi <strong>dosyanÄ±n yolu</strong>, ki bizim Ã¶rneÄŸimizde &quot;<em>deneme.txt</em>&quot; olarak verilmiÅŸ. Ä°kinci parametremiz ise bu dosya Ã¼zerinde yapacaÄŸÄ±mÄ±z <strong>iÅŸlem kipini ve paylaÅŸÄ±m kipini</strong> belirler. Ä°ÅŸlem ve paylaÅŸÄ±m kipleri &quot;<font
face="Courier New"><strong>or</strong></font>&quot; kelimesi ile birleÅŸtirilerek kullanÄ±lÄ±r. Åžimdi bu kiplerin ne olduÄŸuna bakalÄ±m:</p><p><strong>Ä°ÅŸlem Kipleri: </strong></p><p
align="justify"><font
face="Courier New">fmCreate</font>: Verilen dosya yolunda eÄŸer dosya yoksa oluÅŸturur. EÄŸer dosya var ise Ã¼zerine yazar.</p><p
align="justify"><font
face="Courier New">fmOpenRead</font>: DosyayÄ± sadece okuma amaÃ§lÄ± aÃ§ar.</p><p
align="justify"><font
face="Courier New">fmOpenWrite</font>: DosyayÄ± sadece yazma amaÃ§lÄ± aÃ§ar.</p><p
align="justify"><font
face="Courier New">fmOpenReadWrite</font>: DosyayÄ± hem okuma hem de yazma iÃ§in aÃ§ar.</p><p><strong>PaylaÅŸÄ±m Kipleri:</strong></p><p
align="justify"><font
face="Courier New">fmShareExclusive</font>: DiÄŸer uygulamalarÄ±n, bizim Ã¼zerinde Ã§alÄ±ÅŸtÄ±ÄŸÄ±mÄ±z dosya Ã¼zerinde hem <strong>okuma </strong>hem de <strong>yazma</strong> iÅŸlemlerini <strong>yasaklar</strong>.</p><p
align="justify"><font
face="Courier New">fmShareDenyWrite</font>: DiÄŸer uygulamalar dosyayÄ± okuyabilir fakat Ã¼zerinde <strong>yazma </strong>iÅŸlemi <strong>yapamazlar</strong>.</p><p
align="justify"><font
face="Courier New">fmShareDenyRead</font>: DiÄŸer uygulamalarÄ±n, dosya Ã¼zerinde <strong>okuma </strong>iÅŸlemi yapmasÄ±nÄ± <strong>yasaklar</strong>.</p><p
align="justify"><font
face="Courier New">fmShareDenyNone</font>: Ne okuma ne de yazma yasaÄŸÄ± koyar. Yani diÄŸer uygulamalar, dosya Ã¼zerinde yazma ve okuma yapabilirler.</p><p
align="justify"><font
face="Courier New">fmShareCompat</font>: Eskiden dos zamanlarÄ±nda kullanÄ±lan <em>FCB(File Control Block)</em> ile uyumluluÄŸu saÄŸlamak iÃ§in kullanÄ±lÄ±r. <em>Windows </em>Ã¼zerinde <font
face="Courier New">fmShareExclusive</font>, <em>Linux </em>Ã¼zerinde ise <font
face="Courier New">fmShareDenyNone </font>ile aynÄ±dÄ±r. Bu yÃ¼zden bunu es geÃ§ebilirsiniz.</p><p
align="justify">YukarÄ±da verdiÄŸimiz Ã¶rnekte olduÄŸu gibi iÅŸlem kipleri ve paylaÅŸÄ±m kipleri &quot;<font
face="Courier New"><strong>or</strong></font>&quot; kelimesi ile birleÅŸtirilerek kullanÄ±lÄ±r. Ã–rneÄŸimizde dosya <font
face="Courier New">fmCreate </font>ile eÄŸer yoksa oluÅŸturulacak ve eÄŸer varsa Ã¼zerine yazÄ±lacaktÄ±r. Ve dosya <font
face="Courier New">fmShareDenyNone</font> kipinde olduÄŸu iÃ§in Ã¼zerinde herhangi bir okuma yazma yasaÄŸÄ± bulumamaktadÄ±r.</p><p
align="justify">ArdÄ±ndan <strong><font
face="Courier New">try..finally</font></strong> buloÄŸunda, stream Ã¼zerine yazma iÅŸlemleri yapÄ±lmaktadÄ±r. Åžimdilik bu kÄ±smÄ± anlatmayacaÄŸÄ±z. &Ccedil;Ã¼nkÃ¼ okuma ve yazma iÅŸlemleri iÃ§in ayrÄ± bir konu baÅŸlÄ±ÄŸÄ±mÄ±z bulunmaktadÄ±r.</p><p
align="justify"><font
face="Courier New"><strong>finally</strong></font> bloÄŸunda gÃ¶rdÃ¼ÄŸÃ¼mÃ¼z <font
face="Courier New">Free </font>metodu dosyalar Ã¼zerinde fazladan bir Ã¶nem arz etmektedir. &Ccedil;Ã¼nkÃ¼ bir kez <font
face="Courier New">TFileStream </font>ile bir dosyaya eriÅŸildiÄŸinde, bu stream nesnesi <font
face="Courier New">Free </font>oluncaya yani yok edilinceye kadar, dosyanÄ±n handle&#8217;Ä± iÅŸletim sistemi tarafÄ±ndan tutulur. Dosya handle&#8217;Ä± aktif olduÄŸu sÃ¼rece dosyanÄ±n silinmesi taÅŸÄ±nmasÄ± iÅŸletim sistemi tarafÄ±ndan engellenir. Ve genelde herkesin karÅŸÄ±laÅŸtÄ±ÄŸÄ± &quot;<em>Bu dosya bir uygulama tarafÄ±ndan kullanÄ±yor.</em>&quot; gibi bir mesaj alÄ±rÄ±z. Bunun iÃ§in <em>unlocker</em>, <em>process explorer </em>gibi harici programlar ile aktif kalan bu handle&#8217;lar kapatÄ±larak dosyalar silinebilir. Bu yÃ¼zden okuma yazma iÅŸlemlerimiz biter bitmez stream nesnemizi <font
face="Courier New">Free </font>yapmalÄ±yÄ±z.</p><p
align="justify">KÄ±saca bir stream nesnesini oluÅŸturmak iÃ§in aÅŸaÄŸÄ±daki <strong>ÅŸablon</strong>u kullanmalÄ±yÄ±z:</p><pre>
<pre class="brush: delphi">
var
  AStream: TBirStreamSÄ±nÄ±fÄ±;
begin
  AStream := TBirStreamSÄ±nÄ±fÄ±.Create({Stream sÄ±nÄ±fÄ±na ait parametreler...});
  try
    //Stream Ã¼zerinde okuma yazma iÅŸlemleri
  finally
    AStream.Free;
  end;
end;
</pre></pre><h1>Stream &Uuml;zerinde Okuma-Yazma Ä°ÅŸlemleri</h1><p
align="justify">Stream&#8217;ler Ã¼zerinde yazma iÅŸlemleri iÃ§in baÅŸlÄ±ca <font
face="Courier New">Write </font>ve <font
face="Courier New">WriteBuffer </font>metodlarÄ± ve okuma iÅŸlemleri iÃ§in de <font
face="Courier New">Read </font>ve <font
face="Courier New">ReadBuffer </font>metodlarÄ± tanÄ±mlanmÄ±ÅŸtÄ±r. Åžimdi gÃ¶receÄŸimiz iÅŸlemler <em>Win32</em>&#8216;ye gÃ¶re anlatÄ±lacaktÄ±r. Ä°leride ayrÄ± bir baÅŸlÄ±k halinde <font
face="Courier New">TStream </font>sÄ±nÄ±fÄ±nÄ±n <em>.NET</em> Ã¼zerinde nasÄ±l yazma okuma yapabileceÄŸiniz de gÃ¶receÄŸiz. AyrÄ±ca .NET iÃ§inde bulunan <font
face="Courier New">Stream </font>sÄ±nÄ±flarÄ±na deÄŸineceÄŸiz.</p><p
align="justify">Stream Ã¼zerinde yapÄ±lan okuma yazma iÅŸlemleri bir <strong>iÅŸaretÃ§i </strong>vasÄ±tasÄ± ile yapÄ±lÄ±r. Bu iÅŸaretÃ§i hangi pozisyonda ise o pozisyonda okuma ve yazma iÅŸlemi yapÄ±lÄ±r. Ä°lk stream nesnesi oluÅŸturulduÄŸunda iÅŸaretÃ§inin pozisyonu <strong>sÄ±fÄ±rdÄ±r</strong>. Bu metodlar Ã§aÄŸrÄ±ldÄ±ÄŸÄ± vakit, yani her okuma ve yazma iÅŸleminin <strong>sonunda </strong>stream iÅŸaretÃ§isi <strong>bir sonraki</strong> pozisyona kayar. Stream iÅŸaretÃ§isi, stream verisinin sonuna gelip gelmediÄŸini test etmek iÃ§in <font
face="Courier New">Eof </font>metodu kullanÄ±lÄ±r.Bu paragraf streamlerin Ã§alÄ±ÅŸma mantÄ±ÄŸÄ±nÄ±n anlaÅŸÄ±lmasÄ± iÃ§in Ã¶nemlidir. Bu yÃ¼zden dÃ¶nÃ¼p ikinci bir defa okumanÄ±zda fayda var.</p><p
align="justify">Sonunda <font
face="Courier New">Buffer </font>yazan metodlarÄ±n yazmayanlardan farkÄ±ndan sÃ¶z etmek istiyorum. Tek fark, &quot;istisna&quot; (<em>Exception</em>) yakalama Ã¶zelliÄŸidir. Yani mesela <font
face="Courier New">ReadBuffer </font>metodu yine alt planda <font
face="Courier New">Read </font>metodunu Ã§alÄ±ÅŸtÄ±rÄ±r. Fakat <font
face="Courier New">Read</font> metodu bir sorunla karÅŸÄ±laÅŸÄ±r ve okuyamaz ise, <font
face="Courier New">ReadBuffer</font> metodu, <font
face="Courier New">EReadError</font> istisnasÄ±nÄ± yollar. AynÄ± ÅŸekilde <font
face="Courier New">WriteBuffer</font> da sorun yaÅŸadÄ±ÄŸÄ±nda <font
face="Courier New">EWriteError</font> istisnasÄ±nÄ± yollar. BÃ¶ylece okuma ve yazma iÅŸlemlerinde herhangi bir hata olup olmadÄ±ÄŸÄ±nÄ±n tespiti iÃ§in <font
face="Courier New">ReadBuffer</font> ve <font
face="Courier New">WriteBuffer</font> ile beraber istisnalarÄ±n yaklanmasÄ± kafidir.</p><p
align="justify">Okuma ve yazma metodlarÄ±, iÅŸlemlerini bir <strong>buffer</strong> aracÄ±lÄ±ÄŸÄ± ile gerÃ§ekleÅŸtirir. Bu buffer bir <strong><font
face="Courier New">string</font></strong> olabilceÄŸi gibi bir <font
face="Courier New">Integer</font>, bir <strong><font
face="Courier New">record</font></strong> dahi olabilir. Bu yÃ¼zden her veri tipi iÃ§in okuma ve yazma iÅŸlemlerinin nasÄ±l olduÄŸunu ayrÄ± ayrÄ± incelemeye Ã§alÄ±ÅŸalÄ±m.</p><h2>SayÄ±sal DeÄŸelerin OkunmasÄ± ve YazÄ±lmasÄ±</h2><p
align="justify"><font
face="Courier New">Integer</font>, <font
face="Courier New">Byte</font>, <font
face="Courier New">Double</font> gibi sayÄ±sal verileri okuyup yazmak diÄŸerlerine nazaran en basit iÅŸlemdir. Ekstra bir Ã§evirim yapmamÄ±za gerek kalmamaktadÄ±r.</p><p
align="justify">Bunu bir Ã¶rnek Ã¼zerinde gÃ¶relim. Ä°ki adet button yerleÅŸtirelim. Birinin <font
face="Courier New">Caption</font> Ã¶zelliÄŸi &quot;Yaz&quot;, diÄŸerinin <font
face="Courier New">Caption</font> Ã¶zelliÄŸi de &quot;Oku&quot; olsun. &quot;Yaz&quot; butonuna Ã§ift tÄ±klayalÄ±m ve ÅŸunlarÄ± yazalÄ±m:</p><pre>
<pre class="brush: delphi">
procedure TForm1.btnYazClick(Sender: TObject);
var
  BirStream: TFileStream;
  BirInteger: Integer;
  BirDouble: Double;
  BirReal: Real;
  BirByte: Byte;
begin
  BirStream := TFileStream.Create(&#039;c:\deneme.bin&#039;, fmCreate or fmShareDenyNone);
  try
    BirInteger := 15000;
    BirDouble := 1.3;
    BirReal := 123.123123123;
    BirByte := 65;
    BirStream.WriteBuffer(BirInteger, SizeOf(Integer));
    BirStream.WriteBuffer(BirDouble, SizeOf(Double));
    BirStream.WriteBuffer(BirReal, SizeOf(Real));
    BirStream.WriteBuffer(BirByte, SizeOf(Byte));
  finally
    BirStream.Free;
  end;
end;
</pre></pre><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi bir <font
face="Courier New">TFileStream</font> nesnesi oluÅŸturduk ve bu stream nesnesini kullanarak dosyaya bir takÄ±m sayÄ±sal deÄŸerler yazdÄ±rdÄ±k. Mesela ilk yazdÄ±rma Ã¶rneÄŸimizde <em>buffer</em>, <font
face="Courier New">Integer</font> tipinde bir deÄŸiÅŸkendir. Bu <font
face="Courier New">Integer</font> deÄŸeri yazdÄ±rÄ±rken ne kadar yazdÄ±rÄ±lmasÄ± gerektiÄŸini <font
face="Courier New">WriteBuffer</font> metodunun <strong>ikinci</strong> parametresi olarak giriyoruz. Yani yazdÄ±racaÄŸÄ±mÄ±z bu buffer kaÃ§ byte yer tutacak, onu ikinci parametre olarak giriyoruz. Ã–rneÄŸimizde, bu parametre olarak <font
face="Courier New">Integer</font>&#8216;Ä±n boyutunu giriyoruz. Bunun iÃ§in <font
face="Courier New">SizeOf</font> fonksiyonundan faydalanÄ±yoruz. Help dosyasÄ±na baktÄ±ÄŸÄ±mÄ±zda, <font
face="Courier New">Integer</font>&#8216;Ä±n 4 byte yer kapladÄ±ÄŸÄ±nÄ± gÃ¶rÃ¼rÃ¼z. Burada yaptÄ±ÄŸÄ±mÄ±z iÅŸlem dosyada 4 byte&#8217;lÄ±k bir alana <font
face="Courier New">Integer</font> deÄŸeri yazdÄ±rmaktan ibarettir.</p><p
align="justify">ArdÄ±ndan gelen yazma iÅŸlemleri de aynÄ± mantÄ±k ile yapÄ±lmaktadÄ±r. Burada dikkat etmemiz gereken nokta ikinci parametredir. &Ccedil;Ã¼nkÃ¼ bu parametre yanlÄ±ÅŸ girilirse hem yazmada hem de okumada eksik ve yanlÄ±ÅŸ verilerle karÅŸÄ±laÅŸÄ±rÄ±z. Bu Ã¶rnekten de anladÄ±ÄŸÄ±mÄ±z gibi sayÄ±sal veriler ile uÄŸraÅŸÄ±rken <font
face="Courier New">SizeOf(<em>DeÄŸiÅŸkeTipi</em>)</font> ÅŸeklinde ikinci parametreyi belirlememiz yeterlidir.</p><p
align="justify">Åžimdi bu programÄ± Ã§alÄ±ÅŸtÄ±rÄ±p Yaz butonuna basalÄ±m. Diskin <font
face="Courier New">C:</font> bÃ¶lÃ¼mÃ¼nde <em>deneme.bin</em> isimli bir dosya oluÅŸmuÅŸ olmalÄ±. Herhangi bir hex editor ile (<a
href="http://mh-nexus.de/en/" target="_blank">HxD</a>) bu dosyayÄ± aÃ§Ä±p inceleyebilirsiniz. EÄŸer ayrÄ±ntÄ±sÄ±na girmek isterseniz <font
face="Courier New">Integer</font> ve diÄŸer sayÄ±sal deÄŸerlerin nasÄ±l yazÄ±ldÄ±ÄŸÄ±nÄ± inceleyebilirsiniz. Mesela demiÅŸtik ki dosyamÄ±zÄ±n ilk 4 byte&#8217;Ä±nda bir <font
face="Courier New">Integer</font> bulunmaktadÄ±r. DosyamÄ±zÄ± bir hex editÃ¶r ile aÃ§tÄ±ÄŸÄ±mÄ±zda ilk 4 byte&#8217;Ä±nda <font
face="Courier New">98 3A 00 00</font> yazdÄ±ÄŸÄ±nÄ± gÃ¶rÃ¼rÃ¼z. IBM<em> (x86)</em> tabanlÄ± makinelerde bu veriler tersten yazÄ±lÄ±rlar. Bu yÃ¼zden bu ifadeyi <font
face="Courier New">00 00 3A 98</font> olarak dÃ¼ÅŸÃ¼neceÄŸiz. Hesap makinesini aÃ§Ä±p 16&#8242;lÄ±k <em>Hex</em> moda geÃ§elim. Tabi bunu yapabilmek iÃ§in bilimsel moda geÃ§meniz gerekmektedir. Hex modu seÃ§ili iken <font
face="Courier New">3A98</font>&#8216;i yazalÄ±m. ArdÄ±ndan <em>Dec</em> yani ondalÄ±k olarak her zaman kullandÄ±ÄŸÄ±nÄ±z sayÄ± formatÄ±na Ã§evirelim. Ve karÅŸÄ±mÄ±zda <font
face="Courier New">15000</font> sayÄ±sÄ±nÄ± gÃ¶receÄŸiz ki bu deÄŸer Ã¶rneÄŸimizde <font
face="Courier New">Integer</font> olarak dosyanÄ±n baÅŸ tarafÄ±na yazdÄ±rÄ±lmÄ±ÅŸtÄ±. DiÄŸer veri tiplerinin nasÄ±l kaydedildiÄŸini bu ÅŸekilde inceleyerek bulabilirsiniz.</p><p
align="justify">Åžimdi gelelim bu deÄŸerleri okumaya&#8230; Oku butonumuza Ã§ift tÄ±klayÄ±p ÅŸu kodlarÄ± girelim:</p><pre>
<pre class="brush: delphi">
procedure TForm1.btnOkuClick(Sender: TObject);
var
  DosyaOku: TFileStream;
  BirInteger: Integer;
  BirDouble: Double;
  BirReal: Real;
  BirByte: Byte;
begin
  DosyaOku := TFileStream.Create(&#039;c:\deneme.bin&#039;, fmOpenRead or fmShareDenyNone);
  try
    DosyaOku.ReadBuffer(BirInteger, SizeOf(Integer));
    DosyaOku.ReadBuffer(BirDouble, SizeOf(Double));
    DosyaOku.ReadBuffer(BirReal, SizeOf(Real));
    DosyaOku.ReadBuffer(BirByte, SizeOf(Byte));
    ShowMessage(&#039;Integer: &#039; + IntToStr(BirInteger) + #13 +
      &#039;Double: &#039; + FloatToStr(BirDouble) + #13 +
      &#039;Real: &#039; + FloatToStr(BirReal) + #13 +
      &#039;Byte: &#039; + IntToStr(BirByte)
    );
  finally
    DosyaOku.Free;
  end;
end;
</pre></pre><p
align="justify">Åžimdi bu programÄ± Ã§alÄ±ÅŸtÄ±ralÄ±m ve bu sefer oku butonuna basalÄ±m. Ve karÅŸÄ±mÄ±zda dosyaya yazdÄ±rdÄ±ÄŸÄ±mÄ±z deÄŸerler&#8230;</p><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi okuma iÅŸlemi yazma iÅŸleminden farklÄ± deÄŸil. Ä°htiyacÄ±mÄ±z olan tek ÅŸey bir <strong>buffer</strong> ve bu buffer&#8217;Ä±n tipinin <strong>boyutu</strong>. EÄŸer deÄŸiÅŸken tipinin boyutunu yanlÄ±ÅŸ girersek veya okuma sÄ±rasÄ±nÄ± yer deÄŸiÅŸtirirsek, istediÄŸimiz sonucu alamayÄ±z. &Ccedil;Ã¼nkÃ¼ stream Ã¼zerine yazarken, <strong>bu sÄ±rada</strong> ve <strong>bu deÄŸiÅŸken tipleri</strong> ile yazÄ±lmÄ±ÅŸtÄ±r. Okurken de <strong>aynÄ± sÄ±ra</strong> ve <strong>uzunlukta</strong> okunmalÄ±dÄ±r. Bu yÃ¼zden, bu ÅŸekilde kendi dosya formatlarÄ±mÄ±zÄ± oluÅŸtururken, bir plan Ã¼zerinde dosya formatÄ±nda hangi pozisyonda hangi veri bulunacaÄŸÄ± ve boyutu belirlenmelidir.</p><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi sayÄ±sal verileri okumak ve yazmak hiÃ§ de zor deÄŸil. Åžimdi dilerseniz karakter dizilerini nasÄ±l okuyup yazacaÄŸÄ±mÄ±zÄ± gÃ¶relim.</p><h2>Karakter Dizilerinin Okunup YazÄ±lmasÄ±</h2><p
align="justify">Karakter dizisi dediÄŸimizde aklÄ±mÄ±za gelen ilk deÄŸiÅŸken tipleri <font
face="Courier New">string</font> ve <font
face="Courier New">PChar</font>&#8216;dÄ±r. EÄŸer Delphi 2009&#8242;dan Ã¶nceki bir sÃ¼rÃ¼m kullanÄ±yorsanÄ±z bu deÄŸiÅŸken tipleri <em>ANSI</em>&#8216;dir. Yani her bir karakter <strong>bir byte</strong> yer kaplar. D2009 ve sonrasÄ± iÃ§in her bir karakter <em>Unicode</em> olduÄŸu iÃ§in <strong>2 byte</strong> yer kaplarlar.</p><p
align="justify">Ä°lk Ã¶nce <font
face="Courier New">PChar</font> verilerini nasÄ±l yazÄ±yoruz ve okuyoruz onu gÃ¶relim:</p><pre>
<pre class="brush: delphi">
procedure TForm1.btnYazClick(Sender: TObject);
var
  DosyaYaz: TFileStream;
  Karakterler: PChar;
begin
  DosyaYaz := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmCreate or fmShareDenyNone);
  try
    Karakterler := &#039;http://www.diyezon.com&#039;;
    DosyaYaz.WriteBuffer(Karakterler^, Length(Karakterler));
  finally
    DosyaYaz.Free;
  end;
end;
</pre></pre><p
align="justify">Karakter verililerini yazdÄ±rÄ±rken ve okurken dikkat etmemiz gereken nokta yine verinin <strong>kapladÄ±ÄŸÄ±</strong> alandÄ±r. Karakter dizisinin kapladÄ±ÄŸÄ± alanÄ± hesaplayabilmek iÃ§in <strong>bir karakterin</strong> ne kadar yer kapladÄ±ÄŸÄ±nÄ± bilmemiz gereklidir. Ã–nceden de dediÄŸim gibi, eÄŸer karakterleriniz ANSI ise yani Unicode deÄŸilse, her bir karakter <strong>1 byte</strong> yer kaplar. Bu yÃ¼zden bu Ã¶rneÄŸimizde yazÄ±lacak uzunluk olarak karakter sayÄ±sÄ±nÄ± verdik. &Ccedil;Ã¼nkÃ¼ ANSI karakter katarlarÄ±nda karakter sayÄ±sÄ±, karakter dizisinin boyutuna <strong>eÅŸittir</strong>. Fakat <font
face="Courier New">PChar</font> yerine <font
face="Courier New">PWideChar</font> kullansa idik ya da bu kodlarÄ± D2009 ve Ã¼zeri bir sÃ¼rÃ¼mde Ã§alÄ±ÅŸtÄ±rsa idik her bir karakteri 2 byte olarak alacaktÄ±k. Bu durumda karakter sayÄ±sÄ± karakter dizisinin boyutuna eÅŸit deÄŸil, boyutun <strong>yarÄ±sÄ±</strong> kadarÄ± olacaktÄ±. Yani YukarÄ±daki kodda <font
face="Courier New">PChar</font>&#8216;Ä± <font
face="Courier New">PWideChar</font> yaparsak <font
face="Courier New">WriteBuffer</font> metodunun ikinci paramteresine <font
face="Courier New">Length(Karakterler) * 2</font> yazmamÄ±z gerekiyordu. Bu bahsettiÄŸimizi Ã¶rneÄŸimizde deÄŸiÅŸtirip deneyin ve bir hex editÃ¶r ile her bir karakterin 2 byte yer kapladÄ±ÄŸÄ±na ÅŸahid olun. Ama daha sonra tekrar <font
face="Courier New">PChar</font> olarak deÄŸiÅŸtirip dosyayÄ± tekrar yazÄ±n. &Ccedil;Ã¼nkÃ¼ birazdan yapacaÄŸÄ±mÄ±z okuma iÅŸleminde <font
face="Courier New">PChar</font> olarak okutacaÄŸÄ±z.</p><p
align="justify">Okuma iÅŸlemine geÃ§meden Ã¶nce <font
face="Courier New">WriteBuffer</font> metodunda ilk parametreye bir gÃ¶z atalÄ±m. Burada gÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi <font
face="Courier New">Karakterler</font> deÄŸiÅŸkeninin sonuna <font
face="Courier New">^</font> operatÃ¶rÃ¼nÃ¼ ekledik. Bu operatÃ¶r, iÅŸaretÃ§ilerle (<em>pointer</em>) birlikte kullanÄ±lan Ã¶zel bir operatÃ¶rdÃ¼r. Bir iÅŸaretÃ§inin <strong>iÅŸaret ettiÄŸi esas deÄŸere</strong> eriÅŸmek iÃ§in bu operatÃ¶rÃ¼ kullanÄ±yoruz. Ã–rneÄŸimizde ise PChar tipindeki deÄŸiÅŸkenimizin iÅŸaret ettiÄŸi gerÃ§ek deÄŸeri buffer parametresi olarak girdik. &Ccedil;Ã¼nkÃ¼ <font
face="Courier New">PChar</font> da bir Ã§eÅŸit iÅŸaretÃ§idir. Ve <font
face="Courier New">Karakterler^</font> yazmak ile bu iÅŸaretÃ§inin hafÄ±zada iÅŸaret ettiÄŸi gerÃ§ek karakter verisini buffer olarak girdik.</p><p
align="justify">Åžimdi yazdÄ±rdÄ±ÄŸÄ±mÄ±z bu stream verilerini okuyalÄ±m:</p><pre>
<pre class="brush: delphi">
procedure TForm1.btnOkuClick(Sender: TObject);
var
  DosyaOku: TFileStream;
  Karakterler: PChar;
begin
  DosyaOku := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmOpenRead or fmShareDenyNone);
  try
    Karakterler := AllocMem(22);
    DosyaOku.ReadBuffer(Karakterler^, 22);
    ShowMessage(Karakterler);
  finally
    DosyaOku.Free;
  end;
end;
</pre></pre><p
align="justify">Ä°lk yaptÄ±ÄŸÄ±mÄ±z iÅŸlem <font
face="Courier New">Karakterler</font> deÄŸiÅŸkeni iÃ§in hafÄ±zadan yer ayÄ±rmaktÄ±r. Bunun iÃ§in <font
face="Courier New">AllocMem</font> fonksiyonu kullanÄ±lÄ±r. Tabi bunun iÃ§in okuyacaÄŸÄ±mÄ±z verinin <strong>ne kadar uzunlukta</strong> olduÄŸunu bilmemiz gerekiyor. EÄŸer okuyacaÄŸÄ±mÄ±z karakter verilerinin uzunluÄŸu belli deÄŸilse ya da duruma gÃ¶re boyut <strong>deÄŸiÅŸebiliyorsa</strong> bu durumda daha baÅŸka bir ÅŸeyler yapmamÄ±z gerekecek. Bununla ilgili ayrÄ±ntÄ±lÄ± bilgiyi ilerleyen konularda bulacaÄŸÄ±z. Ama ÅŸimdilik veri uzunluÄŸumuzu <strong>sabit</strong> kabul ederek iÅŸlemlerimizi yapalÄ±m.</p><p
align="justify"><font
face="Courier New">AllocMem</font> ile hafÄ±zadan yer ayÄ±rdÄ±ktan sonra bu hafÄ±za bÃ¶lgesine stream verilerini yerleÅŸtirebiliriz. Bunun iÃ§in yine <font
face="Courier New">ReadBuffer </font>ile stream&#8217;den veri okuyoruz ve buffer&#8217;a atÄ±yoruz. Yine buffer olarak iÅŸaretÃ§inin gerÃ§ek deÄŸerini ifade eden <font
face="Courier New">^</font> operatÃ¶rÃ¼nÃ¼ kullanÄ±yoruz. Ä°kinci parametrede de ne kadar uzunlukta okuyacaÄŸÄ±mÄ±zÄ± belirliyoruz.</p><p
align="justify"><font
face="Courier New">PChar</font> ile veri okuma ve yazma bu ÅŸekilde olmakta. Peki <font
face="Courier New">string</font> bir deÄŸiÅŸkeni nasÄ±l yazÄ±p okuyacaÄŸÄ±z? AslÄ±nda <font
face="Courier New">PChar</font>&#8216;da kullandÄ±ÄŸÄ±mÄ±z yÃ¶ntemden farklÄ± deÄŸil. &Ccedil;Ã¼nkÃ¼ <font
face="Courier New">string</font> ile <font
face="Courier New">PChar </font>arasÄ±nda Ã§ok bÃ¼yÃ¼k bir fark bulunmamakta. Zaten Ã§alÄ±ÅŸma anÄ±nda bu iki tip arasÄ±nda dÃ¶nÃ¼ÅŸÃ¼mler rahatlÄ±kla yapÄ±labilmektedir. Yazma iÃ§in yazdÄ±ÄŸÄ±mÄ±z kodlarÄ± aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim:</p><pre>
<pre class="brush: delphi">
procedure TForm1.btnYazClick(Sender: TObject);
var
  DosyaYaz: TFileStream;
  Karakterler: string;
begin
  DosyaYaz := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmCreate or fmShareDenyNone);
  try
    Karakterler := &#039;http://www.diyezon.com&#039;;
    DosyaYaz.WriteBuffer(Pointer(Karakterler)^, Length(Karakterler));
  finally
    DosyaYaz.Free;
  end;
end;
</pre></pre><p
align="justify">Ã–nceki yazma iÅŸleminde Ã§ok farklÄ± olmadÄ±ÄŸÄ±nÄ± burada gÃ¶rÃ¼yoruz. Tek yaptÄ±ÄŸÄ±mÄ±z iÅŸlem derleyiciye, <font
face="Courier New">string</font> deÄŸiÅŸkene  bir <strong>iÅŸaretÃ§i</strong> gibi davranmasÄ±nÄ± sÃ¶ylÃ¼yoruz. Bu ÅŸekilde derleyici, <font
face="Courier New">string</font> olan <font
face="Courier New">Karakterler</font> deÄŸiÅŸkenini bir iÅŸaretÃ§i gibi dÃ¼ÅŸÃ¼necek ve <font
face="Courier New">^</font> operatÃ¶rÃ¼ ile esas hafÄ±za bÃ¶lgesindeki veriyi buffer olarak kullanacak. Burada <font
face="Courier New">Pointer</font> yerine <font
face="Courier New">PChar</font> yazarak da <em>type casting</em> yapabilirsiniz.</p><p
align="justify">Okuma kodlarÄ± <font
face="Courier New">PChar</font>&#8216;a gÃ¶re fazla ya da eksik deÄŸil. Ã–nceki okuma fonksiyonumuzu aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim.</p><pre>
<pre class="brush: delphi">
procedure TForm1.btnOkuClick(Sender: TObject);
var
  DosyaOku: TFileStream;
  Karakterler: string;
begin
  DosyaOku := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmOpenRead or fmShareDenyNone);
  try
    SetLength(Karakterler, 22);
    DosyaOku.ReadBuffer(Pointer(Karakterler)^, 22);
    ShowMessage(Karakterler);
  finally
    DosyaOku.Free;
  end;
end;
</pre></pre><p
align="justify"><font
face="Courier New">AllocMem</font> yerine <font
face="Courier New">string</font> iÃ§in <font
face="Courier New">SetLength</font> fonksiyonunu kullanÄ±yoruz. BÃ¶ylece string olan deÄŸiÅŸkenimizin boyutunu belirliyoruz. <font
face="Courier New">ReadBuffer</font>&#8216;da yapÄ±lanlar Ã¶nceden anlatÄ±lmÄ±ÅŸtÄ±.</p><p
align="justify">String iÃ§in yaptÄ±ÄŸÄ±mÄ±z bu iÅŸlemler biraz pointer yani iÅŸaretÃ§i bilgisi gerektiren iÅŸlerdi. Halbuki bu pointer iÅŸlerine girmeden de string verileri yazÄ±p okuyabiliriz. Ama ilk Ã¶nce bu ÅŸekilde vermemin sebebi, esasÄ±nda iÅŸin arkaplanda Ã§alÄ±ÅŸma ÅŸeklini gÃ¶stermekti.</p><p
align="justify">AslÄ±nda diziler ve iÅŸaretÃ§i olan PChar gibi karakter katarlarÄ± hafÄ±zada bulunan esas verilerdeki <strong>ilk elemana</strong> iÅŸaret ederler.  Derleyici bu deÄŸiÅŸken tipleri ile uÄŸraÅŸÄ±rken bunlarÄ±n uzunluÄŸundan haberdardÄ±r ve ilk pozisyondan itibaren hafÄ±zada bu deÄŸiÅŸkenler Ã¼zerinde iÅŸlem yapabilir. EsasÄ±nda <font
face="Courier New">PChar</font> ve <font
face="Courier New">string</font>&#8216;de ortak olarak yapÄ±lan iÅŸlem, karakter dizisinin <strong>ilk elemanÄ±nÄ±</strong> buffer olarak girmektir. Her iki durumda da <font
face="Courier New">^</font> operatÃ¶rÃ¼ dizinin hafÄ±zadaki <strong>ilk karakterine</strong> iÅŸaret eder. Geri kalanÄ±nda <font
face="Courier New">Write</font> ya da <font
face="Courier New">Read</font> metodlarÄ± verilen uzunluk kadar bu ilk karakterden itibaren okumaya ya da yazmaya baÅŸlar. YukarÄ±da <font
face="Courier New">string</font> iÃ§in yazdÄ±ÄŸÄ±mÄ±z kodlarÄ± ÅŸu ÅŸekilde daha kolay ve sade bir ÅŸekilde de yazabiliriz:</p><pre>
<pre class="brush: delphi">
procedure TForm1.btnOkuClick(Sender: TObject);
var
  DosyaOku: TFileStream;
  Karakterler: string;
begin
  DosyaOku := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmOpenRead or fmShareDenyNone);
  try
    SetLength(Karakterler, 22);
    DosyaOku.ReadBuffer(Karakterler[1], 22);
    ShowMessage(Karakterler);
  finally
    DosyaOku.Free;
  end;
end;

procedure TForm1.btnYazClick(Sender: TObject);
var
  DosyaYaz: TFileStream;
  Karakterler: string;
begin
  DosyaYaz := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmCreate or fmShareDenyNone);
  try
    Karakterler := &#039;http://www.diyezon.com&#039;;
    DosyaYaz.WriteBuffer(Karakterler[1], Length(Karakterler));
  finally
    DosyaYaz.Free;
  end;
end;
</pre></pre><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi pointer&#8217;lardan kurtulup, bize yakÄ±n olan kodlarÄ± kullandÄ±k ve aynÄ± sonucu aldÄ±k. Ama arka planda derleyici bizim ilk yazdÄ±ÄŸÄ±mÄ±z ve iÅŸaretÃ§ileri kullandÄ±ÄŸÄ±mÄ±z kÄ±sÄ±mdaki gibi Ã§alÄ±ÅŸÄ±r.</p><p
align="justify">Burada tek yaptÄ±ÄŸÄ±mÄ±z iÅŸlem buffer olarak <font
face="Courier New">string</font> deÄŸiÅŸkeninin <strong>ilk karakterini</strong> girmek. Tabi okuma iÅŸleminde yine <font
face="Courier New">SetLength</font>&#8216;i unutmuyoruz. &Ccedil;Ã¼nkÃ¼ okuma iÅŸleminden Ã¶nce hafÄ±zada yeterince yer ayrÄ±lmasÄ± ÅŸarttÄ±r.</p><p
align="justify">Ã–nceden de dediÄŸim gibi uzunluÄŸu sabit uzunlukta olmayan karakter dizileri iÃ§in ayrÄ± bir konu baÅŸlÄ±ÄŸÄ± ayÄ±rdÄ±k. O zamana kadar karakter dizimizin boyutunu sabit kabul edeceÄŸiz.</p><h2>Record&#8217;larÄ±n Stream Verileri Olarak KullanÄ±lmasÄ±</h2><p
align="justify">Genelde stream ile yapÄ±lmak istenen bir gurup veriyi yazmak ve okumaktÄ±r. Bu gurup verileri ise genelde <strong><font
face="Courier New">record</font></strong>&#8216;lar ile tutarÄ±z. Mesela aÅŸaÄŸÄ±da bulunan record iÃ§inde bir Ã§ok deÄŸiÅŸik deÄŸiÅŸken tipi bulunmaktadÄ±r.</p><pre>
<pre class="brush: delphi">
TDosyaBasligi = record
  Imza: string[3];
  Versiyon: Double;
  IcerikBoyutu: Integer;
end;
</pre></pre><p
align="justify">Record&#8217;larÄ± streamler ile beraber kullanÄ±rken ÅŸuna dikkat etmemiz gerekiyor. Bir <font
face="Courier New">record</font> verisini stream ile okuyup yazabilmek iÃ§in, record iÃ§eriÄŸinin <strong>sabit uzunluklu</strong> verilerden oluÅŸuyor olmasÄ±dÄ±r. Aksi halde bu record, Ã¶zel iÅŸlemler yapÄ±lmadÄ±ÄŸÄ± taktirde, streamlerde kullanÄ±lmak iÃ§in elveriÅŸli deÄŸildir. Bu yÃ¼zden yukarÄ±da <font
face="Courier New">string</font> deÄŸiÅŸkenini 3 karakter ile sÄ±nÄ±rlandÄ±rdÄ±k.</p><p
align="justify">Okuma esnasÄ±nda da aynÄ± record verisini kullanarak rahat bir ÅŸekilde okuma iÅŸlemini yapabilriiz. Peki ama bu bize ne avantaj saÄŸlayacak?</p><p
align="justify">Ã–nceki Ã¶rneklerde gÃ¶rdÃ¼ÄŸÃ¼mÃ¼z gibi, herbir <font
face="Courier New">string</font>, <font
face="Courier New">Integer</font>, <font
face="Courier New">Double</font> gibi deÄŸiÅŸkenler iÃ§in ayrÄ± ayrÄ± <font
face="Courier New">Read</font> ve <font
face="Courier New">Write</font> metodlarÄ± kullandÄ±k. Halbuki bu deÄŸiÅŸkenler eÄŸer sabit bir formda ise bunlarÄ± bir paket halinde okuyup yazabilmeliyiz. Ä°ÅŸte bu paket halinde okuyup yazma iÅŸlemi iÃ§in recordlarÄ± kullanÄ±yoruz. Yani yukarÄ±da verdiÄŸimiz <font
face="Courier New">TDosyaBasligi</font> isimli recordu yazabilmek iÃ§in tek tek iÃ§inde bulunan 3 deÄŸiÅŸkeni yazdÄ±rmamÄ±z gerekmiyor. Sadece <font
face="Courier New">TDosyaBasligi</font> isimli recordu yazdÄ±rmamÄ±z kafidir.</p><p
align="justify">Åžimdi yukarÄ±da verdiÄŸmiz recordu <font
face="Courier New"><strong>interface</strong></font> kÄ±smÄ±nda, <font
face="Courier New">TForm</font> tanÄ±mlamasÄ±nÄ±n yukarÄ±sÄ±nda ama <strong><font
face="Courier New">type</font></strong>&#8216;Ä±n altÄ±nda yazalÄ±m. Ve Yaz butonunun <font
face="Courier New">OnClick</font> olayÄ±na ÅŸunlarÄ± yazalÄ±m:</p><pre>
<pre class="brush: delphi">
procedure TForm1.btnYazClick(Sender: TObject);
var
  DosyaYaz: TFileStream;
  Paket: TDosyaBasligi;
begin
  DosyaYaz := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmCreate or fmShareDenyNone);
  try
    Paket.Imza := &#039;DYZ&#039;;
    Paket.Versiyon := 1.2;
    Paket.IcerikBoyutu := 1500;
    DosyaYaz.WriteBuffer(Paket, SizeOf(TDosyaBasligi));
  finally
    DosyaYaz.Free;
  end;
end;
</pre></pre><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi herhangi bir ekstra iÅŸlem yapmadÄ±m. Sanki basit bir sayÄ±sal veriyi yazdÄ±rÄ±r gibi recordumuzu yazdÄ±rdÄ±k. AynÄ± ÅŸekilde okumasÄ±nÄ± da gerÃ§ekleÅŸtirelim:</p><pre>
<pre class="brush: delphi">
procedure TForm1.btnOkuClick(Sender: TObject);
var
  DosyaOku: TFileStream;
  Paket: TDosyaBasligi;
begin
  DosyaOku := TFileStream.Create(&#039;c:\deneme.txt&#039;, fmOpenRead or fmShareDenyNone);
  try
    DosyaOku.ReadBuffer(Paket, SizeOf(TDosyaBasligi));
    ShowMessage(Paket.Imza + #13 + FloatToStr(Paket.Versiyon) + #13 +
      IntToStr(Paket.IcerikBoyutu));
  finally
    DosyaOku.Free;
  end;
end;
</pre></pre><p
align="justify">Bu programÄ± Ã§alÄ±ÅŸtÄ±ralÄ±m ve ilk Ã¶nce Yaz sonra da Oku buttonlarÄ±na tÄ±klayalÄ±m. BÃ¶ylece bir recordu yazÄ±p okuyabildik. Fakat disk Ã¼zerine yazÄ±lan dosyayÄ± bir hex editÃ¶r yardÄ±mÄ± ile incelersek gÃ¶receÄŸiz ki ilk kÄ±sÄ±mda bulunan 3 karakterlik stringten <strong>Ã¶nce 1 byte&#8217;lÄ±k</strong> bir veri bulunmaktadÄ±r. Ã–nceki string yazma iÅŸlemlerinden farklÄ± olarak burada record iÃ§indeki stringlerin sadece verisi yazdÄ±rÄ±lmaz. <font
face="Courier New">String</font> deÄŸiÅŸkeninin <strong>tamamÄ±</strong> record ile beraber yazdÄ±rÄ±lÄ±r. <font
face="Courier New">String</font> deÄŸiÅŸkenin tamamÄ±ndan kastÄ±mÄ±z stringi oluÅŸturan parÃ§alardÄ±r. Bir <font
face="Courier New">string</font>, <font
face="Courier New">PChar</font> gibi karakter dizilerinden farklÄ± olarak ilk <font
face="Courier New">0</font>. baytÄ±nda stringin veri uzunluÄŸunu tutar. Bu Ã¶rneÄŸimizde 3 karakter uzunluÄŸunda olduÄŸu iÃ§in hex editÃ¶rde ilk gÃ¶receÄŸimiz deÄŸer <font
face="Courier New">03</font> deÄŸeridir. Tabi bu tek bytelÄ±k alanda en fazla 255 deÄŸeri yani <font
face="Courier New">FF</font> deÄŸerini tutlabilir. Bu yÃ¼zden sÄ±nÄ±rlÄ± bir <font
face="Courier New">string</font>(<em>literal string</em>) kullanabilmek iÃ§in en fazla 255 karakter kullanabiliriz. Aksi halde daha baÅŸka yollara baÅŸvurmalÄ±yÄ±z. BaÅŸta bulunan <font
face="Courier New">03</font> ifadesini kaldÄ±rÄ±p sadece string verisini yazdÄ±rmak istersek <strong><font
face="Courier New">array</font></strong> kullanmamÄ±z gerekmektedir. <font
face="Courier New">Array</font> kullanÄ±mÄ±nÄ± bir sonraki konuda gÃ¶receÄŸiz.</p><p
align="justify">Sabit uzunluklu recordlarÄ± kaydederken gÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi hiÃ§ zorlanmÄ±yoruz. EÄŸer record iÃ§eriÄŸi burada olduÄŸu gibi sabit uzunluklu deÄŸilse yani record iÃ§ine <font
face="Courier New">PChar</font> ya da limitsiz <font
face="Courier New">string</font> girersek ne yapacaÄŸÄ±z. Bu durumda eÄŸer yapabiliyorsak deÄŸiÅŸken uzunluklu olanlarÄ± recorddan <font
face="Courier New">Ã§Ä±kartÄ±p</font> iÅŸlemlerimizi o ÅŸekilde yapmalÄ±yÄ±z. DeÄŸiÅŸken uzunluklu verileri recorddan <strong>ayrÄ± olarak</strong> okuyup yazmamÄ±z gerekmektedir. Ä°leriki konularÄ±mÄ±zda deÄŸiÅŸken uzunluklu veriler ile nasÄ±l Ã§alÄ±ÅŸacaÄŸÄ±mÄ±zÄ± da gÃ¶receÄŸiz.</p><h2>Dizileri Stream Verisi Olarak Kullanmak</h2><p
align="justify">AslÄ±nda dizileri stream Ã¼zerine yazmak iÃ§in, buraya kadar Ã¶ÄŸrendiÄŸimiz bilgiler yeterli. String&#8217;leri nasÄ±l yazdÄ±rÄ±r ve okutuyorsak, aynÄ± ÅŸekilde array&#8217;leri de yazdÄ±rÄ±p okutabiliyoruz.</p><pre>
<pre class="brush: delphi">
//YazdÄ±rmak iÃ§in
var
  FS: TFileStream;
  BirDizi: array[0..5] of Integer;
begin
  FS := TFileStream.Create(&#039;c:\deneme.bin&#039;, fmCreate or fmShareDenyNone);
  try
    BirDizi[0] := 153;
    BirDizi[1] := 1;
    BirDizi[2] := 3442;
    BirDizi[3] := 902;
    BirDizi[4] := 455;
    FS.WriteBuffer(BirDizi[0], SizeOf(BirDizi));
  finally
    FS.Free;
  end;
end;

//Okutmak iÃ§in
var
  FS: TFileStream;
  BirDizi: array[0..5] of Integer;
begin
  FS := TFileStream.Create(&#039;c:\deneme.bin&#039;, fmOpenRead or fmShareDenyNone);
  try
    FS.ReadBuffer(BirDizi[0], SizeOf(BirDizi));
    ShowMessage(IntToStr(BirDizi[0]) + #13 +
      IntToStr(BirDizi[1]) + #13 +
      IntToStr(BirDizi[2]) + #13 +
      IntToStr(BirDizi[3]) + #13 +
      IntToStr(BirDizi[4]) + #13);
  finally
    FS.Free;
  end;
end;
</pre></pre><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi <strong>ilk elemanÄ±nÄ±</strong> buffer olarak giriyoruz ve ikinci parametre olarak da <strong>dizinin boyutunu</strong> parametre olarak giriyoruz.</p><p
align="justify">EÄŸer <strong>dinamik</strong> array kullanÄ±yorsak okuma iÅŸlemini gerÃ§ekleÅŸtiren <font
face="Courier New">ReadBuffer</font> metodundan Ã¶nce mutlaka <font
face="Courier New">SetLength</font> ile dizinin boyutunu belirlemiÅŸ olmalÄ±yÄ±z. AyrÄ±ca dizinin kapladÄ±ÄŸÄ± alanÄ± bulabilmek iÃ§in dinamik dizinin eleman sayÄ±sÄ± ile elaman tipinin boyutunu Ã§arpmalÄ±yÄ±z. Yani yukarÄ±daki Ã¶rnekte dinamik dizi kullanmÄ±ÅŸ olsa idik <font
face="Courier New">Length(BirDizi) * SizeOf(Integer)</font> kazacaktÄ±k.</p><p
align="justify">Ä°ki ve daha fazla boyuttaki diziler iÃ§in ise, iÃ§ iÃ§e bir <strong><font
face="Courier New">for</font></strong> dÃ¶ngÃ¼sÃ¼ kurularak bir okuma ve yazma algoritmasÄ± geliÅŸtirilebilir.</p><p
align="justify">Bu kÄ±sÄ±m diziler iÃ§in kolay kÄ±sÄ±mdÄ±. &Ccedil;Ã¼nkÃ¼ bunlar Ã¶nceki Ã¶ÄŸrendiklermizden farksÄ±zdÄ±r. Fakat eÄŸer ActiveX ile uÄŸraÅŸÄ±yorsanÄ±z, Word, Excel gibi programlarÄ±n otomosyonu ile uÄŸraÅŸÄ±yorsanÄ±z <strong>variant array</strong>&#8216;ler ile uÄŸraÅŸmÄ±ÅŸsÄ±nÄ±zdÄ±r. Ä°ÅŸte bu durumda variant olan array&#8217;leri stream&#8217;e kaydetmek ve stream&#8217;den okutmak bu kadar kolay deÄŸildir. Ama zor da deÄŸildir. EÄŸer ActiveX ile uÄŸraÅŸmÄ±yorsanÄ±z diÄŸer baÅŸlÄ±ÄŸa atlayabilirsiniz, ya da nasÄ±l yapÄ±ldÄ±ÄŸÄ± hakkÄ±nda fikir sahibi olmak iÃ§in kalÄ±p okuyabilirsiniz.</p><p
align="justify">Bu Ã¶rneÄŸimizde otomosyon ya da ActiveX nesnelerine girmeyeceÄŸim. Bir ÅŸekilde bu nesnelerden variant array verilerini aldÄ±ÄŸÄ±nÄ±zÄ± dÃ¼ÅŸÃ¼nerek haraket edeceÄŸim.</p><pre>
<pre class="brush: delphi">
var
  VariantArray: Variant;
  VArraySize: Integer;
  PArray: Pointer;
  FS: TFileStream;
begin
  VariantArray := ActiveXNesnesi.ArrayDonderenMetod; //Bu kÄ±sÄ±m size ait...
  VArraySize := VarArrayHighBound(VariantArray, 1) - VarArrayLowBound(VariantArray, 1) + 1;
  PArray := VarArrayLock(VaraintArray);
  FS := TFileStream.Create;
  try
    FS.WriteBuffer(PArray^, VArraySize);
  finally
    FS.Free;
  free;
  VarArrayUnlock(VaraintArray);
</pre></pre><p
align="justify">KarÄ±ÅŸÄ±k gibi gÃ¶rÃ¼nse de eÄŸer ActiveX ile uÄŸraÅŸÄ±yorsanÄ±z bu kÄ±sÄ±m size zor gelmeyecektir. Ä°lk baÅŸta bir nesneden variant array deÄŸerini aldÄ±k. Bu deÄŸeri siz delphi iÃ§inde de oluÅŸturabilirsiniz. ArdÄ±ndan bu array&#8217;in boyutunu hesapladÄ±k ve <font
face="Courier New">VArraySize</font> isimli deÄŸiÅŸkene attÄ±k. Burada dikkat etmeniz gereken nokta, bu Ã¶rneÄŸimizde diziyi byte, char gibi her elemanÄ± 1 byte olan bir diziye gÃ¶re hesapladÄ±k. EÄŸer array&#8217;deki elemanlarÄ±n boyutu 1 byte&#8217;dan fazla ise bu durumda:</p><pre>
<pre class="brush: delphi">
VArraySize := (VarArrayHighBound(VariantArray, 1) -
  VarArrayLowBound(VariantArray, 1) + 1) * TVarData(VariantArray).VArray^.ElementSize;
</pre></pre><p
align="justify">gibi bir ÅŸeyler yazmamÄ±z gerekiyordu. Yani eleman sayÄ±sÄ± ile bir elemanÄ±n boyutunu Ã§arpÄ±yoruz. Daha sonraki gelen iÅŸlemlerde, variant array&#8217;in <strong>ilk elemanÄ±nÄ±n</strong> iÅŸaretÃ§isini alÄ±yoruz. Bunun iÃ§in <font
face="Courier New">VarArrayLock</font> fonksiyonundan faydalanÄ±yoruz. Bu iÅŸaretÃ§iyi daha sonra buffer olarak <font
face="Courier New">WriteBuffer</font>&#8216;da kullanÄ±yoruz. Bu iÅŸaretÃ§i ile iÅŸimiz bitince <font
face="Courier New">VarArrayUnlock</font> yapmayÄ± unutmuyoruz.</p><p
align="justify">Variant dizisini stream&#8217;den okurken de <font
face="Courier New">VarArrayCreate</font> fonksiyonunu kullanÄ±yoruz ve yeni bir dizi oluÅŸturuyoruz. ArdÄ±ndan aynÄ± <font
face="Courier New">VarArrayLock</font> ve <font
face="Courier New">VarArrayUnlock</font> iÅŸlemleri arasÄ±nda dizimizi stream&#8217;den okuyoruz. Bu kÄ±smÄ± size bÄ±rakÄ±yorum&#8230;</p><h2>DeÄŸiÅŸken Uzunluktaki Verileri Okuyup Yazmak</h2><p
align="justify">Buraya kadar Ã¶ÄŸrendiÄŸimiz iÅŸlemlerde hep varsayÄ±lan bir uzunluktan bahsettik. Fakat her zaman durum bu ÅŸekilde olmuyor.</p><p
align="justify">Mesela, kullanÄ±cÄ±nÄ±n bir <font
face="Courier New">TMemo</font> bileÅŸenini doldurduÄŸu bir form var. Biz bu <font
face="Courier New">TMemo</font>&#8216;da bulunan yazÄ±yÄ± ve baÅŸka verileri kendi dosya formatÄ±mÄ±zda saklamak istiyoruz. Ya da veritabanÄ±na kendi formatÄ±mÄ±zda kaydetmek istiyoruz. Bu durumda string&#8217;in ne uzunlukta olduÄŸunu <strong>yazarken</strong> bilebiliriz fakat <strong>okurken bilemeyiz</strong>. &Ccedil;Ã¼nkÃ¼ dosya&#8217;da ya da herhangi bir stream&#8217;de kayÄ±tlÄ± bulunan o string&#8217;e ait <strong>uzunluk</strong>, artÄ±k bizim bilgimizin <strong>dÄ±ÅŸÄ±na</strong> Ã§Ä±kmÄ±ÅŸtÄ±r. Buraya kadar yaptÄ±ÄŸÄ±mÄ±z Ã¶rneklerde hep yazma ve okuma iÅŸlemlerini aynÄ± programa koyduk ve aynÄ± Ã§alÄ±ÅŸma zamanÄ±nda iÅŸlettirdik. Bu yÃ¼zden okuduÄŸumuz verilerin boyutunu her zaman biliyorduk. Halbuki okuma fonksiyonu ayrÄ± bir iÅŸlemde ise ya da programÄ± aÃ§Ä±p kapadÄ±ÄŸÄ±mÄ±zda da okuma iÅŸleminin Ã§alÄ±ÅŸmasÄ±nÄ± istiyorsak bu durumda kaydedeceÄŸimiz veriyi Ã¶zel bir biÃ§imde kaydetmeliyiz.</p><p
align="justify">Bu ve bunun gibi durumlarda yapacaÄŸÄ±mÄ±z iÅŸlem Ã§ok basit ve her tÃ¼rlÃ¼ <strong>deÄŸiÅŸken uzunluklu</strong> veri tipi iÃ§in geÃ§erlidir. YapacaÄŸÄ±mÄ±z tek ÅŸey deÄŸiÅŸken uzunluklu olan verinin boyutunu <strong>sabit</strong> bir pozisyona yazmaktÄ±r. ArdÄ±ndan okuma esnasÄ±nda bu sabit pozisyondaki deÄŸeri <strong>okutarak</strong> deÄŸiÅŸken olan verinin boyutu hakkÄ±nda bilgi sahibi olabiliriz.</p><p>Mesela stream formatÄ±mÄ±z ÅŸu ÅŸekilde olsun:</p></p><table
height="94" width="368" cellspacing="1" cellpadding="1" border="1" align="" summary=""><tbody><tr><td><p><strong>Pozisyon</strong></p></td><td><p><strong>Boyut</strong></p></td><td><p><strong>DeÄŸiÅŸken Tipi</strong></p></td><td><p><strong>AÃ§Ä±klama</strong></p></td></tr><tr><td>0</td><td>3 byte</td><td>String[3]</td><td>Dosya Ä°mzasÄ±</td></tr><tr><td>3</td><td>8 byte</td><td>Double</td><td>Versiyonu</td></tr><tr><td>15</td><td>4 byte</td><td>Integer</td><td>Ä°Ã§erik Boyutu</td></tr><tr><td>19</td><td>DeÄŸiÅŸken</td><td>String</td><td>Ä°Ã§erik</td></tr><tr><td>Bilinmeyen</td><td>4 byte</td><td>Integer</td><td>Rastgele</td></tr></tbody></table><p
align="justify">Tabi bu Ã§ok basit bir format ÅŸekli. Normalde bir Ã§ok sabit iÃ§erikle beraber bir Ã§ok deÄŸiÅŸken iÃ§eriÄŸi iÃ§ iÃ§e kullanmamÄ±z gerekebiliyor.</p><p
align="justify">FormatÄ±mÄ±za gÃ¶re ilk 3 byte&#8217;da dosya imzasÄ± bulunacak. ArdÄ±ndan gelen 8 byte dosyanÄ±n versiyonunu tutacak. Ve sonrasÄ±nda gelen 4 byte&#8217;lÄ±k Integer deÄŸer ise bizim Ã¼zerinde uÄŸraÅŸtÄ±ÄŸÄ±mÄ±z esas konudur. &Ccedil;Ã¼nkÃ¼ bu Integer deÄŸer sonrasÄ±nda gelen string iÃ§eriÄŸin boyutunu tutmaktadÄ±r. BÃ¶ylece okuma esnasÄ±nda string verimizi ne kadar okuyacaÄŸÄ±mÄ±zÄ± belirleyebiliyoruz.</p><p
align="justify">En sonda ise 4 byte&#8217;lÄ±k bir <font
face="Courier New">Integer</font> daha ekledim. Bu deÄŸer aslÄ±nda bu Ã¶rneÄŸimizi iÃ§in gerekli deÄŸil. Fakat burada bir noktaya dikkatinizi Ã§ekmek istediÄŸimden bu deÄŸeri de dosya formatÄ±na ekledim.</p><p
align="justify">DeÄŸiÅŸken uzunlukta olan <font
face="Courier New">string</font>, <font
face="Courier New">array</font> ya da herhangi bir deÄŸiÅŸkeni kaydederken normalde ilk akla gelen stream&#8217;in sonuna kadar okumak olacaktÄ±r. Ya da stream&#8217;in uzunluÄŸundan diÄŸer verilerin boytunu Ã§Ä±karmak olacaktÄ±r. Halbuki iÅŸin iÃ§ine iki veya daha fazla deÄŸiÅŸken uzunlukta veri girdiÄŸinde ve buradaki Ã¶rnekte olduÄŸu gibi deÄŸiÅŸken uzunluktan sonra da bir baÅŸka veri geldiÄŸinde bu mantÄ±k bizi idare etmeyecektir. AynÄ± ÅŸekilde dosya formatÄ±mÄ±zÄ± sÃ¼rekli olarak gÃ¼ncellenebilen bir format ise bu mantÄ±k yine Ã§Ã¶kecektir.</p><p
align="justify">Bu durumda en mantÄ±klÄ± iÅŸlem, deÄŸiÅŸken verilerin <strong>baÅŸÄ±nda</strong> bu verinin uzunluÄŸunu <strong>saklamak</strong> olacaktÄ±r. BÃ¶ylece sonrasÄ±nda gelen deÄŸiÅŸken uzunluktaki veri rahatlÄ±kla okunabilir.</p><p
align="justify">Åžimdi bu anlattÄ±klarÄ±mÄ±zÄ± pratiÄŸe dÃ¶kelim ve yukarÄ±daki stream formatÄ±mÄ±zÄ± yine bir dosya Ã¼zerinde yazÄ±p okuyalÄ±m. Bunun iÃ§in yeni bir uygulama aÃ§Ä±n ve form Ã¼zerine bir adet button ve bir adet memo yerleÅŸtirin.</p><p
align="justify">Unit&#8217;in <strong><font
face="Courier New">interface</font></strong> kÄ±smÄ±nda <font
face="Courier New">TForm1</font> tanÄ±mlamasÄ±nÄ±n hemen Ã¼stÃ¼nde(type bloÄŸu iÃ§inde) ÅŸunlarÄ± yazalÄ±m:</p><pre>
<pre class="brush: delphi">
type
  TDosyaBasligi = record
    Imza: array[0..2] of Char;
    Versiyon: Double;
    IcerikBoyutu: Integer;
  end;
</pre></pre><p
align="justify">Buttonnun <font
face="Courier New">OnClick</font> olayÄ±na aÅŸaÄŸÄ±dakileri yazalÄ±m.</p><pre>
<pre class="brush: delphi">
var
  FS: TFileStream;
  Baslik: TDosyaBasligi;
  Icerik: string;
  Rastgele: Integer;
begin
  FS := TFileStream.Create(&#039;c:\deneme.dyz&#039;, fmCreate or fmShareDenyNone);
  try
    Icerik := Memo1.Lines.Text;
    //BaÅŸlÄ±k bilgilerinin yazÄ±mÄ±
    Baslik.Imza := &#039;DYZ&#039;;
    Baslik.Versiyon := 1.2;
    Baslik.IcerikBoyutu := Length(Icerik);
    FS.WriteBuffer(Baslik, SizeOf(TDosyaBasligi));

    //DeÄŸiÅŸken boyutlu iÃ§eriÄŸin yazÄ±mÄ±
    FS.WriteBuffer(Icerik[1], Length(Icerik)); //Unicode olduÄŸunda Length * 2

    Randomize;
    Rastgele := Random(100);
    FS.WriteBuffer(Rastgele, SizeOf(Integer));
  finally
    FS.Free;
  end;
</pre></pre></p><p
align="justify">Burada aslÄ±nda yeni bir ÅŸeyler gÃ¶rmedik. Sadece Ã¶ÄŸrendiklerimizi bir problemin Ã§Ã¶zÃ¼mÃ¼nde kullandÄ±k.</p><p
align="justify"><font
face="Courier New">Baslik</font> yazdÄ±rÄ±lmadan Ã¶nce, deÄŸiÅŸken uzunluktaki iÃ§eriÄŸimiz olan memo&#8217;nun <font
face="Courier New">Text</font> bilgisinin uzunluÄŸunu, <font
face="Courier New">Baslik</font> record verisi iÃ§ine alÄ±yoruz. ArdÄ±ndan bu recordu stream&#8217;e yazdÄ±ktan sonra, deÄŸiÅŸken iÃ§eriÄŸin uzunluÄŸu da yazÄ±lmÄ±ÅŸ oldu. ArdÄ±ndan normal bir stringi yazdÄ±rÄ±r gibi bÃ¼tÃ¼n karakterlerini stream Ã¼zerine yazdÄ±rdÄ±k. ArdÄ±ndan da rastgele bir sayÄ±yÄ± bu deÄŸiÅŸken uzunluktaki veriden sonra yazdÄ±rdÄ±k. ArtÄ±k programÄ± Ã§alÄ±ÅŸtÄ±rÄ±p Memo iÃ§ine bir ÅŸeyler yazalÄ±m ve button&#8217;a basÄ±p verileri stream Ã¼zerine kaydedilim.</p><p
align="justify">Åžimdi gelelim bu stream formatÄ±nÄ±n okunmasÄ±na&#8230; Bunun iÃ§in ayrÄ± yeni bir uygulama aÃ§alÄ±m ve bir button ekleyelim. Ve bu buttonun <font
face="Courier New">OnClick</font> olayÄ±na geÃ§ip ÅŸunlarÄ± yazalÄ±m:</p><pre>
<pre class="brush: delphi">
var
  FS: TFileStream;
  Baslik: TDosyaBasligi;
  Icerik: string;
  Rastgele: Integer;
begin
  FS := TFileStream.Create(&#039;c:\deneme.dyz&#039;, fmOpenRead or fmShareDenyNone);
  try
    //BaÅŸlÄ±k bilgilerinin okunmasÄ±
    FS.ReadBuffer(Baslik, SizeOf(TDosyaBasligi));

    if Baslik.Imza &lt;&gt; &#039;DYZ&#039; then
    begin
      ShowMessage(&#039;Desteklenmeyen format&#039;);
      Exit;
    end;

    if Baslik.Versiyon &gt; 1.2 then
    begin
      ShowMessage(&#039;Bu format ancak Ã¼st versiyonlarda aÃ§Ä±labilir.&#039;);
      Exit;
    end;

    //DeÄŸiÅŸken boyutlu iÃ§eriÄŸin okunmasÄ±
    SetLength(Icerik, Baslik.IcerikBoyutu);
    FS.ReadBuffer(Icerik[1], Baslik.IcerikBoyutu);
    FS.ReadBuffer(Rastgele, SizeOf(Integer));

    ShowMessage(Icerik + #13 + IntToStr(Rastgele));
  finally
    FS.Free;
  end;
end;
</pre></pre><p
align="justify">Burada yaptÄ±ÄŸÄ±mÄ±z iÅŸlem sadece verilerin okunmasÄ±ndan ibaret. Sadece dikkat etmemiz gereken kÄ±sÄ±m, <font
face="Courier New">ReadBuffer</font>&#8216; dan Ã¶nce <font
face="Courier New">SetLength</font> ile deÄŸiÅŸken uzunlukta olan verinin uzunluÄŸunu belirlememiz gerekiyor.</p><p
align="justify">DeÄŸiÅŸken uzunluktaki stringler bu ÅŸekilde okutulabilir.</p><p
align="justify">Bir kÃ¼Ã§Ã¼k tÃ¼yo olarak, verileri yazdÄ±rdÄ±ÄŸÄ±mÄ±z kÄ±sÄ±mdaki ÅŸu kodlara bir daha gÃ¶z atmanÄ±zÄ± isteyeceÄŸim:</p><pre>
<pre class="brush: delphi">
  Icerik := Memo1.Lines.Text;
  ......
  ......
  Baslik.IcerikBoyutu := Length(Icerik);
</pre></pre><p
align="justify">Bu kodlar <font
face="Courier New">Baslik</font> recordunun yazÄ±lmasÄ±ndan evvel doldurulmaktadÄ±r. Bazen Ã¶yle durumlar oluyorki, veri uzunluÄŸunu verinin stream&#8217;e <strong>tamamen yazdÄ±rÄ±lmasÄ±na</strong> kadar <strong>bilemiyoruz</strong>. Mesela deÄŸiÅŸken uzunlukta bu stringimiz, stream&#8217;e yazdÄ±rÄ±lma esnasÄ±nda belli bir algoritma ile <strong>dinamik</strong> olarak oluÅŸturuluyor olabilir. Bu durumda string verisi tamamen stream Ã¼zerine yazdÄ±rÄ±lmadan, uzunluÄŸunu bilemeyiz. Bu durumda <font
face="Courier New">TStream</font>&#8216;e ait <font
face="Courier New">Seek</font> metodunu kullanacaÄŸÄ±z. Bu metod stream Ã¼zerinde belli bir <strong>pozisyona atlamamÄ±zÄ±</strong> saÄŸlamaktadÄ±r. Bu durumda kodumuz ÅŸÃ¶yle bir ÅŸey olacaktÄ±:</p><pre>
<pre class="brush: delphi">
  //Åžimdilik yer ayÄ±rmak iÃ§in 0 yazdÄ±rÄ±yoruz.
  Baslik.IcerikBoyutu := 0;
  FS.WriteBuffer(Baslik, SizeOf(TDosyaBasligi));

  .....
  .....
  //Stream Ã¼zerine verilerin yazdÄ±rÄ±lmasÄ± ve boyutunun hesaplanmasÄ±...
  //Burada deÄŸiÅŸken uzunluktaki veri yazdÄ±rÄ±lmakla birlikte boyutu da hesaplanÄ±yor.
  .....
  .....

  FS.Seek(15, soFromBeginning);
  FS.WriteBuffer(IcerikBoyutu, SizeOf(Integer));
</pre></pre><p
align="justify">AynÄ± ÅŸeyi <font
face="Courier New">Baslik</font> recordunu en sonda yazdÄ±rmakla da yapabilrdik. Veya daha baÅŸka yollar ile de bu dediklerimiz yapÄ±labilir. Burada bilmemiz gereken <font
face="Courier New">Seek</font> metodunun kullanÄ±mÄ±dÄ±r. <font
face="Courier New">Seek</font> metodunda ilk parametre olarak <font
face="Courier New">15</font> girdik. &Ccedil;Ã¼nkÃ¼ Ã¶rneÄŸimizdeki stream format tablomuza baktÄ±ÄŸÄ±mÄ±zda 15. byte pozisyonunda iÃ§erik boyutu bulunmaktadÄ±r. <font
face="Courier New">Seek</font> ile stream&#8217;in <strong>yazma iÅŸaretÃ§isini</strong> buraya taÅŸÄ±dÄ±k ve bu pozisyondan sonra 4 byte&#8217;lÄ±k bir <font
face="Courier New">Integer</font> deÄŸer yazdÄ±rdÄ±k. <font
face="Courier New">Seek</font> metodunda kullanÄ±lan ikinci parametre iÃ§in help dosyalarÄ±nÄ± gezebilirsiniz.</p><p
align="justify">DeÄŸiÅŸken uzunlukta olan diziler iÃ§in, yani dinamik diziler iÃ§in de aynÄ± mantÄ±ÄŸÄ± kullanmamÄ±z gerekmektedir. DeÄŸiÅŸken olan dizinin boyutunu da stream Ã¼zerine yazdÄ±rmamÄ±z ve okuma anÄ±nda bu deÄŸeri okuyup diziyi <font
face="Courier New">SetLength</font> ile tekrar oluÅŸturmamÄ±z gerekmektedir. YapacaÄŸÄ±mÄ±z iÅŸlemler aynÄ± olacaÄŸÄ± iÃ§in bu kÄ±smÄ± size bÄ±rakÄ±yorum.</p><p
align="justify">Bu bÃ¶lÃ¼mde bu kadar bilgi yeterli. Gelecek bÃ¶lÃ¼mde stream verilerinin baÅŸka streamler Ã¼zerine aktarÄ±lmasÄ± ve kopyalanmasÄ±, streamler ile nesne ve bileÅŸen kullanÄ±mÄ±, hafÄ±za, resource, veritabanÄ± gibi ortamlarla stream kullanÄ±mÄ± ve son olarak .NET ortamÄ±nda stream kullanÄ±mÄ±ndan bahsedeceÄŸiz. Ä°kinci bÃ¶lÃ¼me geÃ§meden burada anlatÄ±lanlarÄ± iyi bir ÅŸekilde kavrayÄ±p, kendi denemelerinizi yapmanÄ±z gerekmektedir.</p><p
align="justify">EleÅŸtiri ve yorumlarÄ±nÄ±zÄ± bekliyorum&#8230;</p><p
align="justify">Fatih Tolga Ata &#8211; 2008</p></p></p></p> ]]></content:encoded> <wfw:commentRss>http://www.diyezon.com/streamde-uzmanlasalim-bolum-1/feed/</wfw:commentRss> <slash:comments>12</slash:comments> </item> <item><title>Delphi ile Thread(Kanal) KullanÄ±mÄ± &#8211; BÃ¶lÃ¼m 2</title><link>http://www.diyezon.com/delphi-ile-threadkanal-kullanimi-bolum-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=delphi-ile-threadkanal-kullanimi-bolum-2</link> <comments>http://www.diyezon.com/delphi-ile-threadkanal-kullanimi-bolum-2/#comments</comments> <pubDate>Sat, 06 Oct 2007 17:44:45 +0000</pubDate> <dc:creator>Fatih Tolga Ata</dc:creator> <category><![CDATA[Delphi]]></category> <category><![CDATA[kanallar]]></category> <category><![CDATA[kritik bÃ¶lgeler]]></category> <category><![CDATA[muteks]]></category><guid
isPermaLink="false">http://www.diyezon.com/?p=61</guid> <description><![CDATA[Bu bÃ¶lÃ¼mde kanallarÄ± nasÄ±l eÅŸ zamanlÄ± olarak Ã§alÄ±ÅŸtÄ±rabileceÄŸinizi gÃ¶receksiniz. Bunun iÃ§in kritik bÃ¶lgeler ve muteksler ile tanÄ±ÅŸacaksÄ±nÄ±z. AyrÄ±ca kanal uyumlu olmayan VCL&#8217;in, kanallar ile nasÄ±l kullanÄ±labileceÄŸini de gÃ¶receksiniz. Bununla beraber kanal kullanÄ±mÄ±ndaki yaÅŸanan bazÄ± problemlere de deÄŸinmeye Ã§alÄ±ÅŸacaÄŸÄ±z. Ã–zellikle veritabanlarÄ±nÄ± kanallar ile kullanmada uyulmasÄ± gereken pÃ¼f noktalarÄ±na da deÄŸinmeye Ã§alÄ±ÅŸacaÄŸÄ±z. AslÄ±nda bu bÃ¶lÃ¼m gerÃ§ekten uzun [...]]]></description> <content:encoded><![CDATA[<p
align="justify">Bu bÃ¶lÃ¼mde kanallarÄ± nasÄ±l eÅŸ zamanlÄ± olarak Ã§alÄ±ÅŸtÄ±rabileceÄŸinizi gÃ¶receksiniz. Bunun iÃ§in <strong>kritik bÃ¶lgeler</strong> ve <strong>muteksler</strong> ile tanÄ±ÅŸacaksÄ±nÄ±z. AyrÄ±ca kanal uyumlu olmayan VCL&#8217;in, kanallar ile nasÄ±l kullanÄ±labileceÄŸini de gÃ¶receksiniz. Bununla beraber kanal kullanÄ±mÄ±ndaki yaÅŸanan bazÄ± problemlere de deÄŸinmeye Ã§alÄ±ÅŸacaÄŸÄ±z. Ã–zellikle veritabanlarÄ±nÄ± kanallar ile kullanmada uyulmasÄ± gereken pÃ¼f noktalarÄ±na da deÄŸinmeye Ã§alÄ±ÅŸacaÄŸÄ±z.</p><p
align="justify">AslÄ±nda bu bÃ¶lÃ¼m gerÃ§ekten uzun oldu. Normalde VCL kullanÄ±mÄ±nÄ± Ã¼Ã§Ã¼ncÃ¼ bir bÃ¶lÃ¼me taÅŸÄ±mayÄ± dÃ¼ÅŸÃ¼nÃ¼yordum. Ama bu konuda istekler olunca birleÅŸtrip yayÄ±nlamayÄ± dÃ¼ÅŸÃ¼dÃ¼m. Ä°Ã§eride sizi iki sayfalÄ±k bir makale bekliyor. Bu yÃ¼zden sayfa sonunda bitti zannedip kapatmayÄ±n!</p><p
align="justify">HazÄ±rsanÄ±z baÅŸlayalÄ±m.</p><p><span
id="more-61"></span></p><h1>Kanallar&#8217;Ä± EÅŸ ZamanlÄ± Olarak &Ccedil;alÄ±ÅŸtÄ±rmak</h1><p
align="justify">Kanallar ile uÄŸraÅŸÄ±rken karÅŸÄ±laÅŸÄ±lan en bÃ¼yÃ¼k sorunlardan bir tanesi de ÅŸÃ¼phesiz kanallarÄ± ortak bir ÅŸekilde sorunsuz olarak Ã§alÄ±ÅŸtÄ±rmaktÄ±r. Eminim kanallar ile uÄŸraÅŸan birisi bÃ¼tÃ¼n kanallar tarafÄ±ndan ortak olarak kullanÄ±lan bir kaynaÄŸa eriÅŸmede problemlerle karÅŸÄ± karÅŸÄ±ya gelmiÅŸtir ve kanallarÄ± bir kÃ¶ÅŸeye itmesine sebep olmuÅŸtur.</p><p
align="justify">Mesela ÅŸu veritabanÄ± problemi size tanÄ±dÄ±k gelecektir. Diyelim ki, iki adet kanalÄ±mÄ±z var ve bunlardan birincisi veritabanÄ±ndaki bir kaydÄ± aÃ§Ä±p deÄŸiÅŸiklik yapmaya baÅŸladÄ±. Sonra ikinci kanal aynÄ± kaydÄ±n belli bÃ¶lÃ¼mlerinde dÃ¼zenlemeler yaptÄ±ktan sonra veriyi kaydetti. ArdÄ±ndan birinci kanal, aynÄ± verilerdeki deÄŸiÅŸikliÄŸini bitirdi ve kaydetti. Birinci kanal, ikinci kanal&#8217;Ä±n deÄŸiÅŸikliklerinden habersiz olduÄŸundan ikinci kanalÄ±n yaptÄ±ÄŸÄ± dÃ¼zenlemeler de uÃ§tu gitti.</p><p
align="justify">Burada okuduÄŸunuz problem, normalde kanallar ve veritabanÄ± ile uÄŸraÅŸan bir Ã§ok programcÄ±nÄ±n baÅŸÄ±na gelmiÅŸ bir problemdir. Bununla birlikte sadece veritabanÄ±nda deÄŸil bir Ã§ok noktada Ã¶zellikle bir dosyayÄ±, bir portu, bir DLL&#8217;i veya baÅŸka bir ÅŸeyi, kanallarÄ±n <strong>ortak </strong>kullanmasÄ±nda hep benzer sÄ±kÄ±ntÄ±larla karÅŸÄ±laÅŸÄ±lmÄ±ÅŸtÄ±r. Bu gibi sÄ±kÄ±ntÄ±larÄ±n ve problemlerin Ã§Ã¶zÃ¼mÃ¼ kanallarÄ± eÅŸ zamanlÄ± kullanÄ±m iÃ§in <strong>kritik bÃ¶lgeler</strong> tanÄ±mlamak ya da <strong>muteksleri</strong> kullanmaktÄ±r. Bu iki yÃ¶ntem de makalemizin konularÄ± arasÄ±ndadÄ±r.</p><h1>Kritik BÃ¶lgeler(Critical Sections)</h1><p
align="justify">Kritik BÃ¶lgeler -<em>ya da baÅŸka yerlerde gÃ¶rebileceÄŸiniz gibi kritik kesimler, bÃ¶lÃ¼mler, vs..</em>- yukarÄ±da anlatÄ±ÄŸÄ±mÄ±z problemdeki, birinci kanalÄ±n kaynaÄŸÄ± kullanmasÄ± esnasÄ±nda ikinci kanalÄ±n bu kaynaÄŸa eriÅŸmesini <u>englelemek</u> iÃ§in kullanÄ±lÄ±r. Birinci kanal iÅŸini yapÄ±yorken, ikinci kanal&#8217;a Ã§alÄ±ÅŸmasÄ± iÃ§in bir zaman dili ayrÄ±lmaz. BÃ¶ylece birinci kanal iÅŸini bitirene kadar ikinci kanal Ã§alÄ±ÅŸtÄ±rÄ±lmaz.</p><p
align="justify"> Bunun iÃ§in Ã¶rnek bir uygulamada yukarÄ±daki anlattÄ±ÄŸÄ±mÄ±z senaryolara benzer bir problem oluÅŸturalÄ±m ve Ã§Ã¶zÃ¼mÃ¼nÃ¼ aramaya Ã§alÄ±ÅŸalÄ±m.</p><p
align="justify">Diyelim ki, iki adet kanalÄ±mÄ±z var ve bu kanallar bir dÃ¶ngÃ¼nÃ¼n her adÄ±mÄ±nda bir dizi iÅŸlem gerÃ§ekleÅŸtiriyor. Ve bu gerÃ§ekleÅŸtirdikleri iÅŸlemler iÃ§in ortak kullandÄ±klarÄ± global olarak tanÄ±mlanmÄ±ÅŸ bir deÄŸiÅŸken olsun. Meseleyi anlatabilmek iÃ§in iki kanalÄ±nda yaptÄ±ÄŸÄ± iÅŸlemlerin sonucunun aynÄ± olmasÄ±nÄ± saÄŸlamak istiyorum. BÃ¶ylece problem daha iyi anlaÅŸÄ±labilecek.</p><p
align="justify">Birinci kanal bir dÃ¶ngÃ¼nÃ¼n her adÄ±mÄ±nda global deÄŸiÅŸkenimize teker teker harfler ekliyor ve sonuÃ§ta deÄŸiÅŸkenimizde bir yazÄ± oluÅŸuyor. AynÄ± iÅŸlemi ikinci kanalÄ±mÄ±z da yapÄ±yor ve sonuÃ§ olarak birinci kanal ile aynÄ± yazÄ±yÄ± Ã¼retiyorlar. YanlÄ±z ikinci kanal harfleri teker teker eklemek yerine <u>ikiÅŸer ikiÅŸer</u> ekliyor. Ekleme iÅŸlemi Ã§ok hÄ±zlÄ± olduÄŸundan problemin oluÅŸmasÄ± iÃ§in aralara <em>Sleep </em>rutinini ekleyerek iÅŸlemi birazcÄ±k yavaÅŸlatÄ±yoruz. Åžimdi bu mantÄ±ÄŸÄ±mÄ±zÄ± koda dÃ¶kmeye baÅŸlayalÄ±m.</p></p><p
align="justify"> Yeni bir VCL uygulamasÄ± aÃ§alÄ±m ve bir adet button ekleyelim. AÅŸaÄŸÄ±daki gibi unitin var bloÄŸunda global bir deÄŸiÅŸken tanÄ±mlayalÄ±m:</p><pre>
<pre class="brush: delphi">var
  Form1: TForm1;
  SonucYazi: string; //Global deÄŸiÅŸkenimiz</pre></pre><p
align="justify">ArdÄ±ndan buttonun OnClick olayÄ±nÄ± aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim.</p><pre>
<pre class="brush: delphi">procedure TForm1.Button1Click(Sender: TObject);
var
  Kanal1ID, Kanal2ID: DWORD;
begin
  CreateThread(nil, 0, @Kanal1, nil, 0, Kanal1ID);
  CreateThread(nil, 0, @Kanal2, nil, 0, Kanal2ID);
end;</pre></pre><p
align="justify">Bu iki adet kanalÄ±mÄ±za ait kanal fonksiyonlarÄ±nÄ± da aÅŸaÄŸÄ±daki gibi oluÅŸturalÄ±m:</p></p><pre>
<pre class="brush: delphi">procedure Kanal1;
procedure Kanal2;

...

implementation

...

procedure Kanal1;
var
  i: Integer;
begin
  for i := 0 to 10 do
  begin
    SonucYazi := SonucYazi + &#039;d&#039;;
    Sleep(10);
    SonucYazi := SonucYazi + &#039;i&#039;;
    SonucYazi := SonucYazi + &#039;y&#039;;
    SonucYazi := SonucYazi + &#039;e&#039;;
    Sleep(10);
    SonucYazi := SonucYazi + &#039;z&#039;;
    SonucYazi := SonucYazi + &#039;o&#039;;
    SonucYazi := SonucYazi + &#039;n &#039;;
    Sleep(10);
  end;
end;

procedure Kanal2;
var
  i: Integer;
begin
  for i := 0 to 10 do
  begin
    SonucYazi := SonucYazi + &#039;di&#039;;
    Sleep(10);
    SonucYazi := SonucYazi + &#039;ye&#039;;
    SonucYazi := SonucYazi + &#039;zo&#039;;
    Sleep(10);
    SonucYazi := SonucYazi + &#039;n &#039;;
  end;
end;</pre></pre><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi iki kanal fonksiyonu da aynÄ± sonucu Ã¼retiyor. Ama sonucu Ã¼retme yollarÄ± farklÄ±. AyrÄ±ca iki kanal da peÅŸ peÅŸe oluÅŸturulup Ã§alÄ±ÅŸtÄ±rÄ±lÄ±yor. Forma bir adet daha button ekleyelim ve bize sonucu gÃ¶stersin. Bunun iÃ§in ikinci butonumuzun OnClick olayÄ±nÄ± aÅŸaÄŸÄ±daki gibi dÃ¼zenleyelim:</p><pre>
<pre class="brush: delphi">procedure TForm1.Button2Click(Sender: TObject);
begin
  ShowMessage(SonucYazi);
end;</pre></pre><p
align="justify">Bu programÄ± Ã§alÄ±ÅŸtÄ±rdÄ±ktan sonra ve kanallarÄ± birinci dÃ¼ÄŸme ile Ã§alÄ±ÅŸtÄ±rdÄ±ktan sonra sonuÃ§ yazÄ±nÄ±n &quot;diyezon diyezon diyezon &#8230;&quot; gibi bir ÅŸey olmasÄ±nÄ± isteriz. Yani bir for dÃ¶ngÃ¼sÃ¼nÃ¼n bir adÄ±mÄ± <u>tamamlanmadan</u> <em>SonucYazi </em>isimli global deÄŸiÅŸkene <u>mÃ¼dahale</u> olmasÄ±nÄ± istemeyiz. Halbuki programÄ± Ã§alÄ±ÅŸtÄ±rdÄ±ÄŸÄ±nÄ±zda sonucun hiÃ§ de bÃ¶yle olmadÄ±ÄŸÄ±nÄ± gÃ¶receÄŸiz. <em>Kanal1</em> iÅŸini bitirip &quot;diyezon &quot; yazmadan <em>Kanal2</em> iÅŸe karÄ±ÅŸmÄ±ÅŸ ve aralarda kendi harflerini eklemiÅŸtir. Hakeza bu, <em>Kanal2</em> iÃ§in de geÃ§erlidir. Yani <em>Kanal2</em>, dÃ¶ngÃ¼nÃ¼n bir adÄ±mÄ±nÄ± bitirip istenilen sonucu veremeden <em>Kanal1</em> global deÄŸiÅŸkenimize mÃ¼dahale etmiÅŸtir.</p><p
align="justify">Burada verdiÄŸimiz Ã¶rnek biraz soyut kaÃ§abilir. &Ccedil;Ã¼nkÃ¼ yaptÄ±ÄŸÄ±mÄ±z iÅŸlemden sonuÃ§ olarak elimize bir ÅŸey geÃ§miyor. Ama karÅŸÄ±laÅŸacaÄŸÄ±nÄ±z sorunlar hep bu tarzda sorunlardÄ±r. KarÅŸÄ±laÅŸtÄ±ÄŸÄ±nÄ±z sorunlarÄ± verdiÄŸimiz bu Ã¶rnek ile kÄ±yaslama yapabilirsiniz. Mesela biz bu Ã¶rneÄŸimizde iÅŸlem adÄ±mlarÄ±nÄ± yavaÅŸlatmak iÃ§in <em>Sleep</em> rutinini kullandÄ±k. Normal hayatta kanallar ile uÄŸraÅŸÄ±rken zaten yaptÄ±ÄŸÄ±mÄ±z iÅŸlemlerin adÄ±mlarÄ± <em>Sleep</em> rutinini aratmamaktadÄ±r. Mesela bir veritabanÄ± tablosunda <em>Edit</em> ve <em>Post</em> gibi metodlarÄ± kullandÄ±ÄŸÄ±mÄ±zda belli bir miktar iÅŸlemin tamamlanmasÄ±nÄ± bekleriz. Bir de eÄŸer sizde sonuÃ§ dÃ¼zgÃ¼n Ã§Ä±kÄ±yorsa yine sÃ¶ylÃ¼yorum iÅŸlemciniz, bu makaleyi yazdÄ±ÄŸÄ±m sÄ±ralardaki iÅŸlemcimden hÄ±zlÄ± demektir. Bu durumda <em>Sleep</em> rutinine verdiÄŸimiz deÄŸerleri Ã§ok az miktarlarda artÄ±rmayÄ± deneyin.</p><p
align="justify">Sadede gelelim ve problemi anladÄ± isek ÅŸÃ¶yle bir soruyu kafamÄ±za getirelim: Bir kanal belli bir iÅŸini bitirmeden Ã¶nce diÄŸer kanallarÄ±n mÃ¼dahalesini nasÄ±l <u>engelleyebiliriz</u>?</p><p
align="justify">CevabÄ± zaten bu bÃ¶lÃ¼mÃ¼n baÅŸÄ±nda verdik. Bunun iÃ§in belli yerleri <u>kritik bÃ¶lge</u> ilan edeceÄŸiz. Bir kanalda kritik bÃ¶lge ilan ettiÄŸimiz yerdeki kodlar Ã§alÄ±ÅŸmaya baÅŸladÄ±ÄŸÄ± sÄ±rada, diÄŸer kanallardaki <strong><u>aynÄ±</u></strong> kritik bÃ¶lgedeki kodlar iÅŸletilmez ve bekler. Yani <strong>aynÄ± kritik bÃ¶lgeye sahip kanallardan aynÄ± anda sadece bir bÃ¶lgedeki kodlar Ã§alÄ±ÅŸtÄ±rÄ±labilir</strong>. BÃ¶ylece diÄŸer kanallarÄ±n istenilmeyen mÃ¼dahalesi engellenmiÅŸ olur.</p><p
align="justify">Bir Kritik bÃ¶lge tanÄ±mlamak iÃ§in bilmemiz gereken Ã¼Ã§ dÃ¶rt adet Windows apisi vardÄ±r.</p><p
align="justify"><font
face="Courier New"><strong>InitializeCriticalSection</strong></font>: Bu fonksiyon kritik bÃ¶lge&#8217;yi temsil eden recordun ilk deÄŸerlerini atamakla sorumludur. Yani kritik bÃ¶lgeyi kullanÄ±ma hazÄ±rlamaktadÄ±r. Genelde formun <em>OnCreate</em> olayÄ±nda kullanÄ±lÄ±r.</p><p
align="justify"><font
face="Courier New"><strong>DeleteCriticalSection</strong></font>: YukarÄ±daki fonksiyonun tam tersi olarak, bu fonksiyon da kritik bÃ¶lgeyi ortadan kaldÄ±rÄ±r. Genelde formun <em>OnDestroy</em> olayÄ±na yerleÅŸtirilir.</p><p
align="justify"><font
face="Courier New"><strong>EnterCriticalSection</strong></font>: Bu fonksiyonu Ã§alÄ±ÅŸtÄ±rdÄ±ÄŸÄ±nÄ±z satÄ±rdan itibaren kritik bÃ¶lgenin baÅŸlangÄ±cÄ±nÄ± belirtirsiniz. Yani Delphi&#8217;deki &quot;<strong><font
face="Courier New">begin</font></strong>&quot; kelimesi gibi dÃ¼ÅŸÃ¼nebilirsiniz.</p><p
align="justify"><font
face="Courier New"><strong>LeaveCriticalSection</strong></font>: Bu fonksiyon ise, Ã§alÄ±ÅŸtÄ±rÄ±ldÄ±ÄŸÄ± satÄ±rla kritik bÃ¶lgeyi sÄ±nÄ±rlandÄ±rÄ±r. Yine Delphi&#8217;deki &quot;<font
face="Courier New"><strong>end</strong></font>&quot; ifadesine benzetebiliriz.</p><p
align="justify">Kritik bÃ¶lgeyi temsil eden record ise <em>TRTLCriticalSection</em> tipindedir. Normalde Windows SDK yardÄ±m dosyalarÄ±nda <em>LPCRITICAL_SECTION</em> ÅŸeklinde tanÄ±mlanmÄ±ÅŸtÄ±r. Ama Delphi ekibi bir Ã§ok windows yapÄ±sÄ±nÄ± tanÄ±mlarken bunlara &quot;<strong>T</strong>&quot; ile baÅŸlayan daha iyi okunur alias isimler vermiÅŸler. Her neyse&#8230;</p><p
align="justify"> Kritik bÃ¶lgenin tanÄ±mlanmasÄ± gayet basittir. Bir kritik bÃ¶lgeyi iÅŸletim sistemine tanÄ±tmak iÃ§in <em>InitializeCriticalSection </em>fonksiyonunu kullanÄ±yoruz. Kritik bÃ¶lge ile iÅŸimiz bittiÄŸinde de <em>DeleteCriticalSection </em>fonksiyonunu Ã§aÄŸÄ±rmayÄ± unutmuyoruz. ArdÄ±ndan kanal fonksiyonlarÄ±mÄ±zda kritik bÃ¶lgeleri belirleyip <u>baÅŸÄ±na</u> <em>EnterCriticalSection </em>ve <u>sonuna</u> <em>LeaveCriticalSection </em>sonksiyonlarÄ±nÄ± koyuyoruz.</p><p
align="justify">Ã–rneÄŸimize dÃ¶nelim ve kritik bÃ¶lgeleri eklemeye baÅŸlayalÄ±m. Bizim mÃ¼dahale istemediÄŸimiz bÃ¶lge, kanal fonksiyonlarÄ±ndaki dÃ¶ngÃ¼lerin her bir <u>adÄ±mÄ±dÄ±r</u>. Yani teker teker veya ikiÅŸer ikiÅŸer ekleme yapÄ±lan kÄ±sÄ±mlarda bir adÄ±m iÅŸini bitirmeden baÅŸka bir kanalÄ±n global deÄŸiÅŸkenimize mÃ¼dahalesini engellemek istiyoruz. KÄ±sacasÄ± kritik bÃ¶lgemiz bu Ã¶rnekte, dÃ¶ngÃ¼nÃ¼n her bir adÄ±mÄ± olmalÄ±dÄ±r.</p><p
align="justify">Ä°lk baÅŸta global olarak bir deÄŸiÅŸken daha tanÄ±mlayalÄ±m. Bu deÄŸiÅŸken bizim kritik bÃ¶lgemizi temsil eden record olsun.</p><pre>
<pre class="brush: delphi">var
  Form1: TForm1;
  SonucYazi: string;
  BirinciKritikBolge: TRTLCriticalSection; //kritik bÃ¶lgemizi temsil ediyor.</pre></pre><p
align="justify">ArdÄ±ndan formun <em>OnCreate </em>ve <em>OnDestroy </em>olaylarÄ±nÄ± aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim.</p><pre>
<pre class="brush: delphi">procedure TForm1.FormCreate(Sender: TObject);
begin
  InitializeCriticalSection(BirinciKritikBolge);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  DeleteCriticalSection(BirinciKritikBolge);
end;</pre></pre><p
align="justify">EÄŸer baÅŸka kritik bÃ¶lgeler de tanÄ±mlamÄ±ÅŸ iseniz bunlarÄ± da <em>InitializeCriticalSection </em>ve <em>DeleteCriticalSection </em>fonksiyonlarÄ±nÄ± kullanarak oluÅŸturmalÄ± ve silme iÅŸlemlerini gerÃ§ekleÅŸtirmelisiniz. Bizim Ã¶rneÄŸimizde bir adet kritik bÃ¶lge yeterlidir.</p><p
align="justify">Åžimidi kanal fonksiyonlarÄ±nda bahsettiÄŸimiz yerleri kritik bÃ¶lge olarak ilan edelim.</p><pre>
<pre class="brush: delphi">procedure Kanal1;
var
  i: Integer;
begin
  for i := 0 to 10 do
  begin
    EnterCriticalSection(BirinciKritikBolge); //BirinciKritikBolge baÅŸlangÄ±cÄ±
    SonucYazi := SonucYazi + &#039;d&#039;;
    Sleep(10);
    SonucYazi := SonucYazi + &#039;i&#039;;
    SonucYazi := SonucYazi + &#039;y&#039;;
    SonucYazi := SonucYazi + &#039;e&#039;;
    Sleep(10);
    SonucYazi := SonucYazi + &#039;z&#039;;
    SonucYazi := SonucYazi + &#039;o&#039;;
    SonucYazi := SonucYazi + &#039;n &#039;;
    Sleep(10);
    LeaveCriticalSection(BirinciKritikBolge); //BirinciKritikBolge bitiÅŸi
  end;
end;

procedure Kanal2;
var
  i: Integer;
begin
  for i := 0 to 10 do
  begin
    EnterCriticalSection(BirinciKritikBolge); //BirinciKritikBolge baÅŸlangÄ±cÄ±
    SonucYazi := SonucYazi + &#039;di&#039;;
    Sleep(10);
    SonucYazi := SonucYazi + &#039;ye&#039;;
    SonucYazi := SonucYazi + &#039;zo&#039;;
    Sleep(10);
    SonucYazi := SonucYazi + &#039;n &#039;;
    LeaveCriticalSection(BirinciKritikBolge); //BirinciKritikBolge bitiÅŸi
  end;
end;</pre></pre><p
align="justify">YapacaÄŸÄ±mÄ±z baÅŸka bir iÅŸlem kalmadÄ±. ProgramÄ± Ã§alÄ±ÅŸtÄ±rÄ±p deneybiliriz. Sonucun &quot;diyezon diyezon diyezon &#8230;&quot; gibi dÃ¼zgÃ¼n olduÄŸunu gÃ¶receÄŸiz. &Ccedil;Ã¼nkÃ¼ Kritik bÃ¶lge tanÄ±mlayarak sadece bir kanalÄ±n kritik bÃ¶lgesini Ã§alÄ±ÅŸtÄ±rmÄ±ÅŸ olduk. BÃ¶ylece bir kanal global <em>SonucYazi </em>deÄŸiÅŸkeni ile uÄŸraÅŸÄ±rken diÄŸer kanal buna mÃ¼dahale edemeyecektir.</p><p
align="justify">Burada bir adet kritik bÃ¶lge tanÄ±mladÄ±k. Sizler ihtiyaca gÃ¶re projelerinizde bir Ã§ok kritik bÃ¶lge tanÄ±mlayabilirsiniz. AyrÄ±ca kritik bÃ¶lgelerin birbirinden <u>baÄŸÄ±msÄ±z </u>hareket ettiÄŸini de aklÄ±nÄ±zdan Ã§Ä±karmayÄ±n. Bazen karÄ±ÅŸtÄ±rÄ±lan nokta bu kÄ±sÄ±m olabiliyor. Mesela bu Ã¶rneÄŸimizde bir adet kritik bÃ¶lge mevcut ama iki farklÄ± yapÄ±lan iÅŸ var.</p><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi kanallarÄ± eÅŸ zamanlÄ± olarak Ã§alÄ±ÅŸtÄ±rmak o kadar da zor deÄŸilmiÅŸ. Tek yaptÄ±ÄŸÄ±mÄ±z bell bÃ¶lgeleri kritik bÃ¶lge olarak ilan etmek. Åžimdi yeni bir kavramla daha tanÄ±ÅŸalÄ±m.</p><h1>Muteksler(Mutex)</h1><p
align="justify">Ä°ngilizce&#8217; de, <strong>mut</strong>ual ve <strong>ex</strong>clusive kelimelerinin birleÅŸiminden meydana gelmiÅŸtir. Dilimizde ise mÃ¼ÅŸterek ve seÃ§kin kelimeleri bu kelimeleri karÅŸÄ±lamaktadÄ±r. Programlama terminolojisinde ise, sadece tek iÅŸlemdeki deÄŸil <strong>birden fazla</strong> iÅŸlemdeki kanallarÄ± eÅŸ zamanlÄ± olarak kullanÄ±lmasÄ±nÄ± saÄŸlayan bir tekniktir.</p><div
align="justify">Muteksler, Ã§alÄ±ÅŸma mantÄ±ÄŸÄ± olarak kritik bÃ¶lgelere benzerler fakat fazladan bir Ã¶zellik olarak sadece aynÄ± iÅŸlem yani sadece aynÄ± uygulamada deÄŸil <strong>baÅŸka </strong>uygulamadaki kanallar ile eÅŸ zamanlÄ± olarak Ã§alÄ±ÅŸmayÄ± da saÄŸlarlar.</div><p
align="justify"><strong>Bir mutekse aynÄ± anda sadece bir tek kanal sahip olabilir. </strong>LiteratÃ¼rde, bu mutekse, bir kanal sahip olduÄŸunda, muteksin kanal tarafÄ±ndan &quot;<strong>tetiklendiÄŸi</strong>&quot; ya da &quot;<strong>tutulduÄŸu</strong>&quot; sÃ¶ylenir. AynÄ± ÅŸekilde eÄŸer kanal bu mutekse sahip deiÄŸilse muteks &quot;<strong>serbestir</strong>&quot; ya da &quot;<strong>tetiklenmemiÅŸtir</strong>&quot; tabirleri kullanÄ±lÄ±r.</p><p
align="justify">Åžu an kafanÄ±zda mutekslerin ne olduÄŸuna dair somut bir dÃ¼ÅŸÃ¼nce oluÅŸmamÄ±ÅŸ olabilir. Ama bÃ¶lÃ¼mÃ¼n sonuna kadar okuduÄŸunuzda neyin ne olduÄŸuna dair bir fikir oluÅŸacaÄŸÄ±na eminim.</p><p
align="justify">Bir muteks, <em>CreateMutex </em>fonksiyonu ile oluÅŸturulur. Bu fonksiyonun tanÄ±mlanmasÄ± ve aÃ§Ä±klamasÄ± aÅŸaÄŸÄ±dadÄ±r.</p><pre>
<pre class="brush: delphi">function CreateMutex(lpMutexAttributes: PSecurityAttributes;
  bInitialOwner: BOOL;
  lpName: PChar): THandle;</pre></pre><p
align="justify"><font
face="Courier New"><strong>lpMutexAttributes</strong></font>: Muteksin gÃ¼venliÄŸi ile ilgli parametredir. Bu parametreye <strong>nil </strong>girerek varsayÄ±lan gÃ¼venlik Ã¶zelliklerini ayarlamÄ±ÅŸ oluyoruz.</p><p
align="justify"><font
face="Courier New"><strong>bInitialOwner</strong></font>: KanalÄ±n bu mutekse sahip olup olmadÄ±ÄŸÄ±nÄ± ya da yukarÄ±da bahsettiÄŸimiz gibi muteksin tetiklenip tetiklenmeyeceÄŸini belirler. True ya da False giriyoruz. Genelde muteksi programÄ±n ana kanalÄ±nda oluÅŸturduÄŸumuzdan, ana kanalÄ±n mutekse sahip olmasÄ±nÄ± istemeyiz. Bu yÃ¼zden genelde bu parametreye False gireriz.</p><p
align="justify"><font
face="Courier New"><strong>lpName</strong></font>: EÄŸer farklÄ± iÅŸlemler bu mutekse eriÅŸecekse bu muteksimize bir isim vermemiz gerekmektedir. Buraya <strong>nil</strong> de girebilirisiniz. Bu durumda isimsiz bir muteksimiz olur.</p><p
align="justify">Bu fonksiyon eÄŸer muteksi oluÅŸturabilirse Ã§Ä±ktÄ± olarak muteksin handle numarasÄ±nÄ± dÃ¶nderir. EÄŸer muteks oluÅŸmamÄ±ÅŸ ise <strong>0</strong> deÄŸerini Ã§Ä±ktÄ± olarak verir.</p><p
align="justify">Muteksleri, kritik bÃ¶lgeler gibi dÃ¼ÅŸÃ¼nebilirsiniz. Kritik bÃ¶lge oluÅŸturmak iÃ§in kullandÄ±ÄŸÄ±mÄ±z <em>InitializeCriticalSection</em> fonksiyonu yerine <strong>CreateMutex</strong> fonksiyonunu, kritik bÃ¶lgenin baÅŸlangÄ±cÄ±nÄ± belirten <em>EnterCriticalSection</em> yerine <strong>WaitForSingleObject</strong> fonksiyonunu, kritik bÃ¶lgenin bitiÅŸini bildiren <em>LeaveCriticalSection</em> fonksiyonu yerine de <strong>ReleaseMutex</strong> fonksiyonunu kullanÄ±yoruz. <strong>CloseHandle </strong>ile de CreateMutex ile oluÅŸan muteksin handle&#8217;Ä±nÄ± kapatmayÄ± da unutmuyoruz.</p></p><p
align="justify">Ä°lk Ã¶nce bir muteks oluÅŸturalÄ±m.</p><pre>
<pre class="brush: delphi">birmuteks := CreateMutex(nil, False, &#039;ornekmuteks&#039;);</pre></pre><p
align="justify">ArdÄ±ndan kritik bÃ¶lgeyi oluÅŸturduÄŸumuz yerlerdeki fonksiyonlarÄ± muteksin fonksiyonlarÄ± ile yer deÄŸiÅŸtiriyoruz. Åžimdilik sadece <em>Kanal1</em> iÃ§in Ã¶rnek verelim.</p><pre>
<pre class="brush: delphi">procedure Kanal1;
var
  i: Integer;
begin
  for i := 0 to 10 do
  begin
    WaitForSingleObject(birmuteks, INFINITE); //Muteksin tetiklenmesini bekle
    SonucYazi := SonucYazi + &#039;d&#039;;
    Sleep(10);
    SonucYazi := SonucYazi + &#039;i&#039;;
    SonucYazi := SonucYazi + &#039;y&#039;;
    SonucYazi := SonucYazi + &#039;e&#039;;
    Sleep(10);
    SonucYazi := SonucYazi + &#039;z&#039;;
    SonucYazi := SonucYazi + &#039;o&#039;;
    SonucYazi := SonucYazi + &#039;n &#039;;
    Sleep(10);
    ReleaseMutex(birmuteks); //Muteksi serbest bÄ±rak.
  end;
end;</pre></pre><p
align="justify">Åžimdi muteksin ne olduÄŸuna dair kafanÄ±zda bir ÅŸeyler ÅŸekillenmeye baÅŸlmamÄ±ÅŸtÄ±r. &Ccedil;Ã¼nkÃ¼ kodlara baktÄ±ÄŸÄ±mÄ±zda <em>WaitForSingleObject </em>fonksiyonu  bir ÅŸeyleri bekliyor ve <em>ReleaseMutex </em>ise bir ÅŸeyi serbest bÄ±rakÄ±yor. <em>WaitForSingleObject</em>, &quot;<strong>tek bir nesne iÃ§in bekle</strong>&quot; gibi bir manasÄ± var. Esas yaptÄ±ÄŸÄ± gÃ¶rev, birinci parametresinde verilen handle numarasÄ±na gÃ¶re bir muteksi <u>beklemektir</u>. Ä°kinci parametresinde ise ne kadar bekleyeceÄŸini belirliyoruz. Bu Ã¶rneÄŸimizde <em>INFINITE </em>(sonsuz) girmekle, bir muteks tetiklenene kadar bekleyeceÄŸini belirttik. Bu parametreye, en fazla ne kadar bekleneceÄŸini milisaniye ÅŸeklinde girebilirsiniz.</p><p
align="justify">Muteksi anlamada genelde verilen Ã¶rnek ve bence en iyi Ã¶rnek bayrak yarÄ±ÅŸÄ±dÄ±r. Bayrak yarÄ±ÅŸlarÄ±nda <u>bir ÅŸeritte ancak bir</u> koÅŸucu koÅŸabilir. <u>BayraÄŸÄ± alan koÅŸmaya baÅŸlar</u>. Bir ÅŸeritte, bayraÄŸa sahip <u>olmayan</u>, koÅŸabilmek iÃ§in bayraÄŸÄ± <u>beklemesi</u> gerekmektedir. BÃ¶yelece her bir ÅŸeritte sadece bir yarÄ±ÅŸÃ§Ä± koÅŸabilir.</p><p
align="justify">Aynen bunun gibi, kanallar Ã§alÄ±ÅŸabilmek iÃ§in mutekse sahip olmalarÄ± gerekmektedir. <u>Mutekse sahip olan koÅŸmaya yani Ã§alÄ±ÅŸmaya baÅŸlar</u>. Mutekse sahip olmayan, muteksin kendisine gelmesini <u>bekler</u>. Bir hatÄ±rlatma olarak, Ã¶nceki paragraflarda sahip olmanÄ±n tetiklemek olduÄŸundan bahsetmiÅŸtik.</p><p
align="justify">Ä°ÅŸte <em>WaitForSingleObject </em>ile muteksin bu kanalÄ±mÄ±za gelmesini beklemiÅŸ oluyoruz. Ve bunu Ã¶rneÄŸimizde, <em>INFINTE </em>yani sonsuz sÃ¼re kadar bekliyoruz. Ve muteksle iÅŸimiz bittiÄŸinde diÄŸer kanallarÄ±n kullanabilmesi iÃ§in muteksi <em>ReleaseMutex </em>ile serbest bÄ±rakÄ±yoruz. Ve yine tekrar ediyorum &quot;<strong>Bir mutekse aynÄ± anda sadece bir tek kanal sahip olabilir.</strong>&quot;</p><p
align="justify"><em>CreateMutex </em>ile oluÅŸturduÄŸumuz muteksin handle&#8217;nÄ± formun <em>OnDestroy </em>olayÄ±nda <em>CloseHandle </em>ile kapatmayÄ± da unutmuyoruz. Yani kritik bÃ¶lgelerde yaptÄ±ÄŸÄ±mÄ±z <em>DeleteCriticalSection </em>yerine</p><pre>
<pre class="brush: delphi">CloseHandle(birmuteks);</pre></pre><p
align="justify">gibi bir ÅŸey yazmalÄ±yÄ±z.</p><p
align="justify">Bu Ã¶rneÄŸi, makaleyi fazla uzatmasÄ±n diye, burada tÃ¼m kodlarÄ±nÄ± yazmayacaÄŸÄ±m. Muteks Ã¶rnek projesini <a
href="http://www.diyezon.com/wp-content/uploads/File/post61/muteks1.rar">buradan</a> indirebilirsiniz.</p><p
align="justify">EÄŸer tek bir muteks deÄŸil de bir den fazla muteksi tetiklemesini bekelemek istersek ne olacak? Bu durumda <strong>WaiÄ±tForMultipleObjects </strong>fonksiyonunu kullanacaÄŸÄ±z. <em>WaitForSingleObject </em>tek bir muteksi beklerken <em>WaitForMultipleObject </em>fonksiyonu birden fazla muteksi beklemektedir. KullanÄ±m aynÄ± olduÄŸu iÃ§in bununla ilgili bir Ã¶rnek yapmayacaÄŸÄ±m. Bu fonksiyon ile iligli tek sÃ¶yleyebileceÄŸim ÅŸey ikinci parametrede beklediÄŸiniz mutekslerin handle&#8217;larÄ±nÄ± dizi ÅŸeklinde girmeniz olacaktÄ±r.</p><h2>BaÅŸka Ä°ÅŸlemlerden Mutekslere Sahip Olma</h2><p
align="justify">DediÄŸimiz gibi, mantÄ±k olarak mutekslerin kritik bÃ¶lgelerden tek farkÄ±, baÅŸka program ve iÅŸlemlerdeki kanallar ile ortak ve eÅŸ zamanlÄ± Ã§alÄ±ÅŸmaya izin vermesidir. Bunun iÃ§in muteksimize bir isim vermemiz gerektiÄŸini sÃ¶ylemiÅŸtik. Ä°ÅŸte bu ismi kullanarak baÅŸka bir iÅŸlem muteksin handle numarasÄ±nÄ± alabilir. Gerisinde de <em>WaitForSingleObject </em>ve <em>ReleaseMutex </em>fonksiyonlarÄ±nda bu handle numarasÄ±nÄ± kullanabiliriz. Yani mevcut bir muteksin handle numarasÄ±nÄ± alabilmek iÃ§in:</p><pre>
<pre class="brush: delphi">birmuteks := OpenMutex(0, False, &#039;ornekmuteks&#039;);</pre></pre><p
align="justify">dememiz yeterli. Bunu yukarÄ±daki Ã¶rneÄŸimizde <em>CreateMutex </em>yerine kullanabilirsiniz. Ama unutmamanÄ±nÄ±z gereken nokta bunun ile <strong>mevcut </strong>bir muteksin handle numarasÄ±nÄ± alÄ±rÄ±z. EÄŸer muteks <em>CreateMutex </em>ile hiÃ§ oluÅŸturulmamÄ±ÅŸ ise bu fonksiyon <strong>0</strong> deÄŸerini dÃ¶nderir.</p><p
align="justify"><em>OpenMutex </em>fonksiyonunun parametreleri <em>CreateMutex </em>ile aynÄ± olduÄŸundan burada fazladan bir aÃ§Ä±klama yapmayacaÄŸÄ±m.</p><p
align="justify">Bu konuda bir Ã¶rnek yapmak isterseniz yukarÄ±da verdiÄŸimiz Ã¶rneÄŸi iki uygulamaya bÃ¶lebilirsiniz. <em>Kanal1</em>&#8216;i birinci uygulamada, <em>Kanal2</em>&#8216;yi de ikinci uygulamada oluÅŸturursunuz. Ve ikisinde de <em>OnCreate</em> olayÄ±nda ÅŸÃ¶yle bir ÅŸey girersiniz:</p><pre>
<pre class="brush: delphi">var
  BirMuteks: THandle;
.....
procedure TForm1.OnCreate(....);
begin
  BirMuteks := OpenMutex(0, False, &#039;ornekmuteks&#039;);
  if BirMuteks = 0 then
    BirMuteks := CreateMutex(nil, False, &#039;ornekmuteks&#039;);</pre></pre><p
align="justify">KÄ±saca burada yaptÄ±ÄŸÄ±mÄ±z iÅŸlem eÄŸer &quot;ornekmuteks&quot; isminde bir mutex henÃ¼z oluÅŸturulmamÄ±ÅŸ ise oluÅŸturuyoruz.</p><p
align="justify">Bu ÅŸekilde iki veya daha fazla sayÄ±da iÅŸlem tek bir muteks Ã¼zerinde kanallarÄ±nÄ± eÅŸ zamanlÄ± olarak Ã§alÄ±ÅŸtÄ±rabilirler. Bu Ã¶rneÄŸi kendiniz yapmaya Ã§alÄ±ÅŸÄ±n. GerÃ§i <a
href="http://www.diyezon.com/wp-content/uploads/File/post61/muteks2.rar">burada</a> yapÄ±lmÄ±ÅŸÄ± var <img
src='http://www.diyezon.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Ama lÃ¼tfen indirip incelemeden Ã¶nce kendiniz yapmayÄ± deneyin.</p><p>&#8212;</p></p><p
align="justify">Ä°ÅŸte size iki adet yÃ¶ntem. Ve ikisi de windows programlamada Ã§ok sÄ±k kullanÄ±lmaktadÄ±r. KanallarÄ± beraber Ã§alÄ±ÅŸtÄ±rmak istediÄŸinizde, istrer muteks kullanÄ±n isterseniz kritik bÃ¶lge tanÄ±mlayÄ±n. Her ikisinin de tanÄ±mlanmasÄ± ve kullanÄ±lmasÄ± Ã§ok kolay. KafanÄ±zdaki &quot;kanal kullanmak Ã§ok zordur&quot; dÃ¼ÅŸÃ¼ncesini birinci bÃ¶lÃ¼mde aÅŸtÄ±ÄŸÄ±nÄ±zÄ± dÃ¼ÅŸÃ¼nÃ¼yorum. Buraya kadar olan kÄ±sÄ±m ile de &quot;kanallarÄ± eÅŸ zamanlÄ± Ã§alÄ±ÅŸtÄ±rmak zordur&quot; dÃ¼ÅŸÃ¼ncesini yendiÄŸinizi zannediyorum.</p><p
align="justify">Peki muteks ve kritik bÃ¶lge arasÄ±nda tercih yapmak gerekirse hangisini tercih etmeliyiz. Bence performans aÃ§Ä±sÄ±ndan pek fark olmaz. SeÃ§im noktanÄ±z ÅŸu olmalÄ±. EÄŸer, tek bir iÅŸlemden deÄŸil de bir Ã§ok iÅŸlemden yani bir Ã§ok programdan oluÅŸan bir gurubun kanallarÄ± ortak ve eÅŸ zamanlÄ± kullanmasÄ±nÄ± dÃ¼ÅŸÃ¼nÃ¼yorsak kesinlikle muteks kullanmalÄ±yÄ±z. Aksi durumda yani eÅŸ zamanlÄ± Ã§alÄ±ÅŸacak olan kanallar sadece tek bir iÅŸlemde bulunuyorlarsa o zaman seÃ§im size kalmÄ±ÅŸ. Hangisi rahatÄ±nÄ±za gidiyorsa onu kullanabilirsiniz.</p><p
align="justify">Åžimdi farklÄ± bir konuya geÃ§iÅŸ yapalÄ±m. HazÄ±rsanÄ±z ikinci sayfadan devem edelim.</p> ]]></content:encoded> <wfw:commentRss>http://www.diyezon.com/delphi-ile-threadkanal-kullanimi-bolum-2/feed/</wfw:commentRss> <slash:comments>19</slash:comments> </item> <item><title>Delphi ile Thread(Kanal) KullanÄ±mÄ± &#8211; BÃ¶lÃ¼m 1</title><link>http://www.diyezon.com/delphi-ile-threadkanal-kullanimi-bolum-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=delphi-ile-threadkanal-kullanimi-bolum-1</link> <comments>http://www.diyezon.com/delphi-ile-threadkanal-kullanimi-bolum-1/#comments</comments> <pubDate>Tue, 02 Oct 2007 14:27:48 +0000</pubDate> <dc:creator>Fatih Tolga Ata</dc:creator> <category><![CDATA[Delphi]]></category> <category><![CDATA[kanallar]]></category><guid
isPermaLink="false">http://www.diyezon.com/?p=58</guid> <description><![CDATA[YaptÄ±ÄŸÄ±mÄ±z projelerin bir bÃ¶lÃ¼mÃ¼ eninde sonunda bu konuya dayanÄ±yor. Genelde kanal gerekli olduÄŸu halde Timer ya da Application.ProcessMessages gibi Ã§arelere gitmeye Ã§alÄ±ÅŸÄ±yoruz Ve devamÄ±nda hem gÃ¶rsel hem de iÅŸleyiÅŸ aÃ§Ä±sÄ±ndan istemediÄŸimiz sonuÃ§larla karÅŸÄ±laÅŸÄ±yoruz. Halbuki kanallarÄ±n kullanÄ±lmasÄ± sanÄ±ldÄ±ÄŸÄ± kadar zor deÄŸildir. Bu Ã¶n yargÄ±yÄ± bu makalede aÅŸmaya Ã§alÄ±ÅŸacaÄŸÄ±z. Bu makale, ileri seviye Windows programcÄ±lÄ±ÄŸÄ±na geÃ§iÅŸ kapÄ±sÄ±dÄ±r. [...]]]></description> <content:encoded><![CDATA[<p
align="justify">YaptÄ±ÄŸÄ±mÄ±z projelerin bir bÃ¶lÃ¼mÃ¼ eninde sonunda bu konuya dayanÄ±yor. Genelde kanal gerekli olduÄŸu halde Timer ya da Application.ProcessMessages gibi Ã§arelere gitmeye Ã§alÄ±ÅŸÄ±yoruz Ve devamÄ±nda hem gÃ¶rsel hem de iÅŸleyiÅŸ aÃ§Ä±sÄ±ndan istemediÄŸimiz sonuÃ§larla karÅŸÄ±laÅŸÄ±yoruz. Halbuki kanallarÄ±n kullanÄ±lmasÄ± sanÄ±ldÄ±ÄŸÄ± kadar zor deÄŸildir. Bu Ã¶n yargÄ±yÄ± bu makalede aÅŸmaya Ã§alÄ±ÅŸacaÄŸÄ±z.</p><p
align="justify">Bu makale, ileri seviye Windows programcÄ±lÄ±ÄŸÄ±na geÃ§iÅŸ kapÄ±sÄ±dÄ±r. Bu makeledeki konularÄ± Ã¶ÄŸrendikten sonra Win32 programcÄ±lÄ±ÄŸÄ±nÄ±n en gÃ¼Ã§lÃ¼ Ã¶zelliklerini Ã¶ÄŸrenmiÅŸ olacaksÄ±nÄ±z.</p><p
align="justify">YanlÄ±z &quot;ileri seviye&quot; tabiri gÃ¶zÃ¼nÃ¼zÃ¼ korkutmasÄ±n. &Ccedil;Ã¼nkÃ¼ makeleyi bitirdiÄŸinizde thread kullanÄ±mÄ±nÄ±n aslÄ±nda ne kadar kolay olduÄŸunu gÃ¶receksiniz. Bununla birlikte bu makalede bu konu ile ilgili her ayrÄ±ntÄ±yÄ± anlatabilmemiz iÃ§in yÃ¼zlerce sayfalÄ±k kitap yazmamÄ±z gereklidir. Bu yÃ¼zden burada iÅŸin mantÄ±ÄŸÄ±nÄ± kapÄ±p, ihtiyacÄ±nÄ±z oldukÃ§a yardÄ±m dosyalarÄ±na mÃ¼racaat etmeniz gerekebilir.</p><p
align="justify">Kanallar hakkÄ±nda hiÃ§ bir bilginiz olmayabilir. Bu makalede iÅŸin temelinden alacaÄŸÄ±z ve makaleyi bitirdiÄŸinizde kendi programlarÄ±nÄ±za kanal ekleyebilecek duruma geleceÄŸinize inanÄ±yorum.</p><p
align="justify">Bu makale serisinde kanallar temelden anlatÄ±lmakla beraber, ileri seviye kanal kullanÄ±mÄ±, VCL bileÅŸenlerinde kanal kullanÄ±mÄ± ve Muteksler de ana konularÄ±mÄ±z arasÄ±na girecektir.</p><p><span
id="more-58"></span></p><h1>GiriÅŸ</h1><p
align="justify">Ä°lk baÅŸta bir kaÃ§ teorik bilgi ile baÅŸlamak istiyorum. Bu bilgilieri olabildiÄŸince sÄ±kmadan, kÄ±sa tutmaya Ã§alÄ±ÅŸacaÄŸÄ±m.</p><p
align="justify">Disk Ã¼zerindeki her bir dosya Ã§alÄ±ÅŸtÄ±rÄ±ldÄ±ÄŸÄ±nda artÄ±k windows iÃ§in birer <strong>iÅŸlem</strong>(<em>process</em>) olurlar. Bir <strong>iÅŸlem </strong>Windows iÃ§in fazla bir ÅŸey ifade etmez. &Ccedil;Ã¼nkÃ¼ iÅŸlemler sadece hafÄ±zada belli bir bÃ¶lgede var olmaktan sorumludur. Esas iÅŸlemi yapan kÄ±sÄ±m <strong>kanallardÄ±r</strong>(<em>thread</em>). Bir iÅŸlem en az bir adet kanala sahiptir. Win 3.1 gibi iÅŸletim sistemleri sadece bir adet kanala sahiptir. Ama Windows 95 ve Ã¼stÃ¼, Unix, OSX gibi iÅŸletim sistemleri birden fazla kanala sahip olabilirler.</p><p
align="justify">Ä°ÅŸletim sistemi bir programÄ± ya da bir DLL&#8217;i ilk baÅŸta iÅŸlem olarak hafÄ±zaya taÅŸÄ±r. Bu esnada iÅŸlem eylemsiz olarak durur. Bu iÅŸleme ait kanallar ise bizim belirlediÄŸimiz Ã¶lÃ§Ã¼de programÄ±n kodlarÄ±nÄ± Ã§alÄ±ÅŸtÄ±rmaya baÅŸlar.</p><div
align="justify"> Yine teorik olarak bilmemiz gereken diÄŸer bir terim de quantum deÄŸeridir. Her kanalÄ±n windows tarafÄ±ndan atanmÄ±ÅŸ bir iÅŸletilme sÃ¼resi vardÄ±r. Ve terim olarak quantum olarak isimlendirilir. Bunun sadece tanÄ±mÄ±nÄ± bilmeniz yeterli.</div><p
align="justify">Her kanal, Ã§alÄ±ÅŸma esnasÄ±nda kendi eax, ebx, edx gibi register verilerini tutan bir yapÄ±ya sahiptir. Bu yapÄ±ya <strong>context</strong>(<em>iÃ§erik</em>) adÄ± verilmektedir. Bu yapÄ±nÄ±n Delphi&#8217;deki karÅŸÄ±lÄ±ÄŸÄ± <em>TContext </em>olup, Windows unitindedir. Bu record tipini incelediÄŸinizde bir Ã§ok register&#8217;Ä± barÄ±ndÄ±rdÄ±ÄŸÄ±nÄ± gÃ¶receksiniz. EÄŸer <a
href="http://www.diyezon.com/?p=45">buradaki</a> Delphi ve Assembler ile ilgili makaleyi ve <a
href="http://www.diyezon.com/?p=47">buradaki</a> fonksiyon Ã§aÄŸÄ±rÄ±m makenizmalarÄ±nÄ± okudu iseniz ÅŸimdi anlatacaklarÄ±mÄ±z size tanÄ±dÄ±k gelecektir. &Ccedil;Ã¼nkÃ¼ kanallarÄ±n iÅŸleyiÅŸ mantÄ±ÄŸÄ± fonksiyon Ã§aÄŸÄ±rÄ±mlarÄ±na benzemektedir. Ama devam edebilmek iÃ§in bunlarÄ± okumak zorunda deÄŸilsiniz.</p><p
align="justify">Her bir kanal sahip olduÄŸu Ã¶nceliÄŸe gÃ¶re iÅŸletim sistemi tarafÄ±ndan iÅŸleme alÄ±nacaktÄ±r. Bu iÅŸleme alÄ±ÅŸ esnasÄ±nda sahip olduÄŸu <em>context</em>&#8216;deki register deÄŸerleri yÃ¼klenir. Esp, Ebp, Eip gibi registerlar da yÃ¼klendiÄŸinden, kanal Ã¶nceden kaldÄ±ÄŸÄ± yerden Ã¶nceki stack deÄŸerlerine gÃ¶re iÅŸlemine devam edecektir. Ve yine Ã¶nceliÄŸine gÃ¶re belli bir sÃ¼re sonunda iÅŸletim sistemi bu kanalÄ± durdurup register deÄŸerlerini <em>context </em>yapÄ±sÄ±nda saklar. Daha sonra diÄŸer bir kanalÄ±n context verisini yÃ¼kleyerek baÅŸka bir kanalÄ± iÅŸlemeye geÃ§er. Ve hakeza bu iÅŸlem tÃ¼m kanallar iÃ§in devam edip gider. Ä°ÅŸletilme ve geÃ§iÅŸ sÃ¼releri Ã§ok kÄ±sa olduÄŸundan, biz sanki aynÄ± anda tÃ¼m kanallar iÅŸletiliyormuÅŸ gibi zannederiz. Halbuki bÃ¼tÃ¼n kanallar belli bir sÄ±ra ile Ã§ok kÄ±sa sÃ¼relerde iÅŸletilip diÄŸer bir kanala geÃ§ilmektedir. Yani her kanal aynÄ± anda Ã§alÄ±ÅŸmaz, biz Ã¶yle zannederiz. Tabi bu anlattÄ±klarÄ±mÄ±z tek iÅŸlemci ve tek Ã§ekirdek iÃ§in geÃ§erlidir. KanallarÄ±n iÅŸletilme sÃ¼relerini ise kanallarÄ±n <strong>Ã¶nceliÄŸi </strong>belirlemektedir. Hangi kanal daha yÃ¼ksek Ã¶ncelikli ise o kanal daha fazla iÅŸletilme sÃ¼resine sahip olur. EÄŸer kanal arkaplanda Ã§alÄ±ÅŸma Ã¼zere ayarlanmÄ±ÅŸ ise, diÄŸer kanallar iÅŸlemlerini tamamladÄ±ktan sonra ancak bu kanala sÄ±ra gelecektir. EÄŸer kanal Ã§ok yÃ¼ksek Ã¶nceliÄŸe sahip ise uzun bir sÃ¼re bu kanal iÅŸleme devam edecek ve diÄŸer kanallara sÄ±ra gelmeyecektir.</p><p
align="justify">Demek ki, aynÄ± anda bir kaÃ§ iÅŸlem yapmak istiyorsak kafa patlatÄ±p, parmak yormamÄ±za gerek yokmuÅŸ. &Ccedil;Ã¼nkÃ¼ iÅŸletim sistemi zaten sizin iÃ§in bu sistemi kurmuÅŸtur. Sadece biraz vaktiniz ayÄ±rmanÄ±z ve kanallar nasÄ±l oluÅŸturuluyor Ã¶ÄŸrenmeniz yeterlidir.</p></p><h1>Kanal OluÅŸturma YÃ¶ntemleri</h1><p
align="justify">AslÄ±nda bÃ¶yle bir baÅŸlÄ±kla konuya giriÅŸ yapmak istemezdim. Ama kanal oluÅŸturmayÄ± Ã¶ÄŸrenmeden Ã¶nce bir kaÃ§ ÅŸeyi aÃ§Ä±ÄŸa kavuÅŸturmak istiyorum. Gerek forumlardan gerekse haber guruplarÄ±ndan kanallarla ilgili gelen sorulardan bir Ã§oÄŸu kanallarÄ±n yanlÄ±ÅŸ oluÅŸturulmasÄ± Ã¼zerine kaynaklanan yanlÄ±ÅŸlÄ±klardan gelmektedir.</p><p
align="justify">Normalde bir kanal windows ortamÄ±nda <em>CreateThread</em> Windows API&#8217;si ile oluÅŸturulur. Fakat VCL bize <em>TThread </em>isminde bir sÄ±nÄ±f da sunmuÅŸtur. KullanÄ±m aÃ§Ä±sÄ±ndan ayÄ±rt edebileceÄŸiniz temel nokta ÅŸudur. EÄŸer kanalda yapacaÄŸÄ±nÄ±z iÅŸlemler VCL sÄ±nÄ±flarÄ±nÄ± etkilemesi gerekiyorsa <em>TThread </em>sÄ±nÄ±fÄ±nÄ± kanal oluÅŸturmak iÃ§in kullanÄ±yoruz. Yok eÄŸer VCL sÄ±nÄ±flarÄ±nÄ± ilgilendiren bir iÅŸlem sÃ¶z konusu deÄŸilse <em>CreateThread</em> API&#8217;sini kullanÄ±yoruz. Bunun neden bÃ¶yle olduÄŸunu ileride VCL ve Kanal kullanÄ±mÄ± ile alakalÄ± baÅŸlÄ±kda vereceÄŸim. Muhtemelen BÃ¶lÃ¼m 2&#8242;de gÃ¶receksiniz. Bu yÃ¼zden biraz sabÄ±r.</p><p
align="justify">BaÅŸlarken bu ÅŸekilde bir giriÅŸ yapmamÄ±n sebibi buradan kaynaklanÄ±yor. Bir Ã§ok kiÅŸi belki de Windows API&#8217;lerine karÅŸÄ± bir soÄŸukluktan dolayÄ± <em>CreateThread </em>ile uÄŸraÅŸmak istemiyor ve <em>CreateThread</em> ile ilgili kÄ±sÄ±mlarÄ± gÃ¶zÃ¼ kapalÄ± atlayabiliyor. Bu yÃ¼zden eksik kanal bilgisi ile ileride bir Ã§ok sorunla karÅŸÄ±laÅŸabiliyor. Ama ÅŸimdi gÃ¶receÄŸimiz gibi kanal oluÅŸturma iÅŸlemi sanÄ±ldÄ±ÄŸÄ± kadar zor ve karmaÅŸÄ±k bir iÅŸlem deÄŸil.</p><h1>Bir Kanal OluÅŸturalÄ±m</h1><p
align="justify">Kanal oluÅŸturma ile sorumlu Windows fonksiyonu <em>CreateThread </em>fonksiyonudur ve aÅŸaÄŸÄ±daki gibi tanÄ±mlanmÄ±ÅŸtÄ±r:</p><pre>
<pre class="brush: delphi">
function CreateThread(lpThreadAttributes: Pointer;
  dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine;
  lpParameter: Pointer; dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall;
</pre></pre><p
align="justify"> Bu fonksiyonun parametrelerinin kÄ±saca aÃ§Ä±klamasÄ±nÄ± verelim.</p><p
align="justify"><font
face="Courier New"><strong>lpThreadAttributes</strong></font>: KanalÄ±mÄ±za atanacak olan bir Ã§ok gÃ¼venlik Ã¶zelliÄŸini belirtmemize yarar. EÄŸer nil girerseniz varsayÄ±lan gÃ¼venlik Ã¶zellikleri kullanÄ±lacaktÄ±r. Win9x ve WinMe iÃ§in bu deÄŸer <font
face="Courier New"><strong>nil</strong></font> olmalÄ±dÄ±r. Bu konu ile alakalÄ± daha fazla bilgi almak iÃ§in sdk yardÄ±m dosyalarÄ±ndan <em>SECURITY_ATTRIBUTES</em> baÅŸlÄ±ÄŸÄ±na mÃ¼racaat edebilirsiniz.</p><p
align="justify"><font
face="Courier New"><strong>dwStackSize</strong></font>: EÄŸer kanal iÃ§in Ã¶zel bir stack bÃ¼yÃ¼klÃ¼ÄŸÃ¼ belirlemeyecekseniz bu deÄŸeri <strong>0</strong> olarak girmelisiniz. BÃ¶ylelikle kanalÄ±n stack bÃ¼yÃ¼klÃ¼ÄŸÃ¼ program ile aynÄ± olacaktÄ±r. GerektiÄŸinde stack boyutu otomatik olarak geniÅŸletilebilir.</p><p
align="justify"><font
face="Courier New"><strong>lpStartAddress</strong></font>: Bu parametre esas iÅŸi gÃ¶ren parametredir. &Ccedil;Ã¼nkÃ¼ kanal Ã§alÄ±ÅŸmaya bu parametredeki fonksiyon iÅŸaretÃ§isi ile beraber baÅŸlar. Burada tek yapmamÄ±z gereken fonksiyonun isminin Ã¶nÃ¼ne <strong>@</strong> iÅŸareti vererek girmektir.</p><p
align="justify"><font
face="Courier New"><strong>lpParameter</strong></font>: Bir Ã¶nceki parametrede girdiÄŸimiz kanal fonksiyonuna parametre yollamak istiyorsanÄ±z, bu parametrelerin iÃ§inde bulunduÄŸu bir record&#8217;un adresini buraya girmelisiniz. AyrÄ±ca record haricinde karakter veya sayÄ± deÄŸelerini de parametre olarak yollayabiliriz.</p><p
align="justify"><font
face="Courier New"><strong>dwCreationFlags</strong></font>: Bu parametre ile kanalÄ±n oluÅŸturulur oluÅŸturulmaz Ã§alÄ±ÅŸÄ±p Ã§alÄ±ÅŸmayacaÄŸÄ±nÄ± belirliyoruz. EÄŸer bu parametreye <em>CREATE_SUSPENDED</em> girerseniz, kanal oluÅŸturulur fakat kendisine Ã§alÄ±ÅŸmaya baÅŸlamasÄ± iÃ§in izin verilmez. Bu durumda siz <em>ResumeThread</em> fonksiyonu ile bu kanala Ã§alÄ±ÅŸma talimatÄ± vermedikÃ§e kanal o ÅŸekilde Ã§alÄ±ÅŸmadan duracaktÄ±r. Bir kez <em>ResumeThread</em> ile Ã§alÄ±ÅŸmaya baÅŸladÄ±ktan sonra <em>SuspendThread</em> ile tekrar kanalÄ± durdurabilirsiniz. EÄŸer bu parametreye <strong>0</strong> girerseniz, kanal oluÅŸturulur oluÅŸturulmaz Ã§alÄ±ÅŸmak iÃ§in sÄ±raya girecektir.</p><p
align="justify"><font
face="Courier New"><strong>lpThreadId</strong></font>: Bu parametreye kanal kimlik ID&#8217;si atanÄ±r. Buraya deÄŸeri olmayan bir Dword deÄŸiÅŸken giriyoruz. DeÄŸiÅŸken gireceÄŸiz Ã§Ã¼nkÃ¼ &quot;<strong>var</strong>&quot; olarak tanÄ±mlanmÄ±ÅŸ. &Ccedil;Ã¼nkÃ¼ kanal oluÅŸturulduktan sonra Windows NT,2000 ve Ã¼stÃ¼ iÅŸletim sistemlerinde kanalÄ±n ID&#8217;si bu deÄŸiÅŸkene yÃ¼klenir. Windows 9x/Me iÅŸletim sistemlerinde bu deÄŸer daima 0&#8242;dÄ±r.</p><p
align="justify">Åžimdi gelin bu fonksiyonu kullanarak bir kanal oluÅŸturalÄ±m.</p><pre>
<pre class="brush: delphi">var
  KanalID: DWORD;
begin
  CreateThread(nil, 0, @KanalFonksiyonu, nil, 0, KanalID);</pre></pre><p
align="justify">Ä°ÅŸte hepsi bu! Tek yaptÄ±ÄŸÄ±mÄ±z sadece gerekli parametreleri kullanmak, gerisini duruma gÃ¶re <strong>nil</strong> veya <strong>0</strong> yapmak. Bu fonskiyon Ã§aÄŸrÄ±ldÄ±ÄŸÄ±nda <em>KanalFonksiyonu </em>isimli fonksiyonumuz kanal iÃ§inde Ã§alÄ±ÅŸmaya baÅŸlayacaktÄ±r.</p><p
align="justify">Dilerseniz <em>KanalFonksiyonu </em>isimli fonksiyonumuzun tanÄ±mlamasÄ±nÄ± ÅŸimdi yapacaÄŸÄ±mÄ±z Ã¶rnek iÃ§inde verelim.</p><h2> Basit Bir Ã–rnek</h2><p
align="justify">Åžimdi oluÅŸturduÄŸumuz bu kanalÄ±n nasÄ±l Ã§alÄ±ÅŸtÄ±ÄŸÄ±nÄ± basit bir Ã¶rnek ile gÃ¶rmeye Ã§alÄ±ÅŸalÄ±m. Yeni bir uygulama oluÅŸturalÄ±m ve Form Ã¼zerine bir adet button ve bir adet label koyalÄ±m. Button&#8217;nun <em>Caption </em>Ã¶zelliÄŸini &quot;OluÅŸtur ve &Ccedil;alÄ±ÅŸtÄ±r&quot; olarak deÄŸiÅŸtirelim. Ve Button&#8217;nun <em>OnClick </em>olayÄ±na kanalÄ±mÄ±zÄ± oluÅŸturan ÅŸu kodlarÄ± girelim:</p><pre>
<pre class="brush: delphi">procedure TForm1.Button1Click(Sender: TObject);
var
  KimlikID: DWORD;
begin
  CreateThread(nil, 0, @KanalFonksiyonu, nil, 0, KimlikID);
end;</pre></pre><p
align="justify">Åžimdi de kanalÄ±mÄ±zda esas iÅŸi yapan <em>KanalFonksiyonu </em>isimli fonksiyonumuzun tanÄ±mlamasÄ±nÄ± girelim:</p><pre>
<pre class="brush: delphi">function KanalFonksiyonu(P: Pointer): Longint; stdcall;

...

implementation

...

function KanalFonksiyonu(P: Pointer): Longint; stdcall;
var
  i: Integer;
  Toplam: Int64;
begin
  Toplam := 0;
  for i := 0 to 1000000000 do
  begin
    Toplam := Toplam + i;
    Toplam := Toplam shl 4;
  end;
  Form1.Label1.Caption := &#039;Kanal iÅŸlemini tamamladÄ±. SonuÃ§:&#039; + IntToStr(Toplam);
end;</pre></pre><div
align="justify"><p>Kanal fonksiyonumuzun tanÄ±mlamasÄ±nÄ± istediÄŸimiz gibi yapabilirdik. Burada mesela <font
face="Courier New">P: Pointer</font> parametresine ihtiyaÃ§ yoktu. AyrÄ±ca <em>Longint </em>Ã§Ä±ktÄ±sÄ±nÄ± vermeye de ihtiyacÄ±mÄ±z yok. <em>CreateThread</em> fonksiyonunun parametre aÃ§Ä±klamalarÄ±nÄ± hatÄ±rlarsanÄ±z, kanal fonksiyonumuza belli parametreler yollayabiliyorduk. Ä°ÅŸte bu parametreleri pointer olarak buradan alÄ±yoruz. Ama bu meseleye sonra geÃ§eceÄŸiz. AyrÄ±ca fonksiyon tanÄ±mlamasÄ±ndaki <em>stdcall </em>ifadesine yabancÄ± iseniz <a
href="http://www.diyezon.com/?p=47">buradaki </a>fonksiyon Ã§aÄŸÄ±rÄ±m makenizmalarÄ± ile ilgili makaleyi okuyabilirsiniz.</p></div><p
align="justify">Bu fonksiyonda ekstra bir ÅŸey yapmÄ±yoruz. Sadece bir for dÃ¶ngÃ¼sÃ¼ var ve matematiksel bir iÅŸlem yapÄ±lÄ±yor. For dÃ¶ngÃ¼sÃ¼ bittiÄŸinde ise formdaki label&#8217;a bir sonuÃ§ yazdÄ±rÄ±yoruz.</p><p
align="justify">Bu for dÃ¶ngÃ¼sÃ¼nÃ¼, ayrÄ± bir kanalda deÄŸil de programÄ±n ana kanalÄ±nda Ã§alÄ±ÅŸtÄ±rmaya kalksaydÄ±k muhtemelen <em>Application.ProcessMessages</em> ve <em>TTimer</em> gibi Ã§Ã¶zÃ¼mlere gidecektik. Bu durum da Ã§ok fazla miktarda performans dÃ¼ÅŸÃ¼klÃ¼ÄŸÃ¼ne sebep olacaktÄ±. AyrÄ±ca iÅŸlemlerimiz genelde buradaki gibi basit matematiksel iÅŸlemler olmadÄ±ÄŸÄ±ndan, programda Ã§Ã¶kmelere ve donmalara sebep olacaktÄ±k.</p><p
align="justify">Bu programÄ± Ã§alÄ±ÅŸtÄ±ralÄ±m ama button&#8217;a basmayalÄ±m. EÄŸer aÃ§Ä±k deÄŸilse View menÃ¼sÃ¼nden &quot;Thread Status&quot; penceresini ve &quot;Event Log&quot; penceresini aÃ§alÄ±m ve gÃ¶rebileceÄŸimiz bir kÃ¶ÅŸeye yerleÅŸtirelim. EÄŸer BDS 2005 ve Ã¼stÃ¼ kullanÄ±yorsanÄ±z bu pencereler debug esnasÄ±nda altta gÃ¶rÃ¼nÃ¼r biÃ§imde hazÄ±r olacaklardÄ±r.</p><p
align="justify">ArdÄ±ndan buttona bir kez basalÄ±m ve &quot;Thread Status&quot; penceresine yeni bir eleman eklendiÄŸine dikkat edelim. EÄŸer buradaki eleman Ã§ok Ã§abuk bir ÅŸekilde gÃ¶rÃ¼nÃ¼p kayboldu ise iÅŸlemciniz benimkinden hÄ±zlÄ± demektir <img
src='http://www.diyezon.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Bu yÃ¼zden for dÃ¶ngÃ¼sÃ¼ndeki limit deÄŸeri biraz artÄ±rÄ±p tekrar Ã§alÄ±ÅŸtÄ±ralÄ±m.</p><p
align="justify">Button&#8217;a her tÄ±kladÄ±ÄŸÄ±nÄ±zda &quot;Thread Status&quot; pencersinden de takip edebileceÄŸiniz gibi yeni bir kanal eklenecek. Tabi butona basma iÅŸini o kadar Ã§ok abartmayÄ±n. Her kanal oluÅŸturulduÄŸunda kendisine bir ID atanacak. Ã–rneÄŸimizde bu deÄŸer <em>KimlikID</em> deÄŸiÅŸkeninde tutuluyor. &quot;Thread Status&quot; pencersinde ise ThreadID sÃ¼tununda bu deÄŸeri gÃ¶rebiliriz. Her kanal iÅŸlemini bitirdiÄŸinde &quot;Thread Status&quot; pencersinden kaybolduÄŸunu gÃ¶receksiniz. AynÄ± ÅŸekilde &quot;Event Log&quot; pencersinde de kanal&#8217;Ä±n ID&#8217;sine gÃ¶re baÅŸlama ve bitiÅŸi ile ilgili mesajlarÄ± gÃ¶rebilirsiniz.</p><p
align="justify">Kanal Ã§alÄ±ÅŸÄ±rken program Ã¼zerinde istediÄŸiniz iÅŸleme devam edebilirsiniz. Formu taÅŸÄ±yabilir, boyutlandÄ±rabilir, baÅŸka bileÅŸen ve nesneler var ise onlarÄ± kullanabilirsiniz. Ve bunu yaparken bir yandan kanal(lar) da Ã§alÄ±ÅŸmaktadÄ±r. AynÄ± kanal fonksiyonunu doÄŸrudan Ã§aÄŸÄ±rmaya kalktÄ±ÄŸÄ±mÄ±zda formumuza dÃ¶ngÃ¼ bitene kadar mÃ¼dahale edemeyecektik.</p><p
align="justify">GÃ¶rdÃ¼ÄŸÃ¼nÃ¼z gibi bir kaÃ§ satÄ±r kod ile kanal oluÅŸturuveriyoruz. Tek bilmemiz gereken kÄ±sÄ±m <em>CreateThread</em> fonksiyonunun parametreleri. BunlarÄ±n Ã§oÄŸunu da kullanmadÄ±k. Ama makalenin ilerleyen kÄ±sÄ±mlarÄ±nda bunlarÄ± da yavaÅŸ yavaÅŸ kullanÄ±ma dahil edeceÄŸiz. Ä°ÅŸte bir tanesi geliyor.</p><h1> Kanal FonksiyonlarÄ±na Parametre GÃ¶nderimi</h1><p><em>CreateThread</em> fonksiyonunun parametrelerini aÃ§Ä±klarken <em>lpParameter</em>&#8216;den sÃ¶z etmiÅŸtik ve bu parametre ile kanal fonksiyonuna istediÄŸimiz parametreyi gÃ¶nderebileceÄŸimizi belirtmiÅŸtik. Åžimdi bunu nasÄ±l yapacaÄŸÄ±mÄ±zÄ± gÃ¶relim.</p><p>Bunun iÃ§in yukarÄ±da yaptÄŸÄ±mÄ±z Ã¶rnekten faydalanacaÄŸÄ±z. Ä°lk baÅŸta <em>type </em>bloÄŸunda aÅŸaÄŸÄ±daki record tanÄ±mlamasÄ±nÄ± yapalÄ±m.</p><pre>
<pre class="brush: delphi">
  PKanalParametresi = ^TKanalParametresi;
  TKanalParametresi = record
    BirParametre: string;
  end;
</pre></pre><p> ArdÄ±ndan kanal fonksiyonumuzu aÅŸaÄŸÄ±daki gibi deÄŸiÅŸtirelim.</p><pre>
<pre class="brush: delphi">function KanalFonksiyonu(P: Pointer): Longint; stdcall;
var
  Parametreler: PKanalParametresi;
begin
  Parametreler := PKanalParametresi(P); //Parametremizi alalÄ±m.
  while True do
  begin
    Form1.Label1.Caption := Form1.Label1.Caption + Parametreler^.BirParametre;
    Sleep(1000); //Ä°ÅŸlemcinin %99 Ã§alÄ±ÅŸmasÄ±nÄ± istemiyiz deÄŸil mi....
  end;
  Dispose(Parametreler);
end;</pre></pre><p>En son olarak button&#8217;nun <em>OnClick </em>olayÄ±nÄ± da aÅŸaÄŸÄ±daki gibi olacak ÅŸekilde deÄŸiÅŸtirelim.</p><pre>
<pre class="brush: delphi">procedure TForm1.Button1Click(Sender: TObject);
var
  KimlikID: DWORD;
  Parametreler: PKanalParametresi;
begin
  New(Parametreler);
  Parametreler^.BirParametre := &#039;a&#039;;
  CreateThread(nil, 0, @KanalFonksiyonu, Parametreler, 0, KimlikID);
end;</pre></pre><p
align="justify">AslÄ±nda Ã§ok fazla bir ÅŸey yapmadÄ±k(en azÄ±ndan siz kopyala yapÄ±ÅŸtÄ±r yaptÄ±nÄ±z:) ). Burada basit bir iÅŸaretÃ§i kullanÄ±mÄ±nÄ± gÃ¶rÃ¼yoruz. Ve parametre olarak bir record&#8217;u kullandÄ±k. Record yerine baÅŸka veri tiplerini de kullanabilirdik. Ama genelde karÅŸÄ±laÅŸÄ±lan sorunlar recordlarÄ± parametre olarak yollamaktan gelmektedir.</p><p
align="justify">En baÅŸta verdiÄŸimiz record tanÄ±mlamasÄ±na bakarsanÄ±z, <em>PKanalParametresi</em> isminde bu recordumuza <u>iÅŸaretÃ§i</u> olan bir tip gÃ¶receksiniz. Parametremizi iÅŸaretÃ§i olarak kullanacaÄŸÄ±mÄ±zdan bu tipe ihtiyacÄ±mÄ±z olacak. ArdÄ±ndan Button&#8217;nun <em>OnClick</em> olayÄ±na bakalÄ±m. Burada Ã¶nceki Ã¶rneÄŸe gÃ¶re fazladan 2 satÄ±r ekledik. Ä°lk baÅŸta <em>var</em> bloÄŸunda <em>Parametreler</em> isminde bir record iÅŸaretÃ§isi tanÄ±mladÄ±k. ArdÄ±ndan iÅŸaretÃ§i hiÃ§ bir ÅŸey ifade etmediÄŸinden, iÅŸaretÃ§iye ait bir recordun hafÄ±zada oluÅŸturulmasÄ± iÃ§in <em>New</em> rutinini kullandÄ±k. DevamÄ±nda bu record&#8217;un deÄŸiÅŸkenlerinden birine bir <em>string </em>deÄŸer atadÄ±k. <em>CreateThread</em> fonksiyonu parametreyi iÅŸaretÃ§i olarak istediÄŸinden buraya direk olarak <em>Parametreler</em> deÄŸiÅŸkenimizi girebiliriz. &Ccedil;Ã¼nkÃ¼ bu deÄŸiÅŸken bir record iÅŸaretÃ§sidir.</p><p
align="justify">En son olarak yeni kanal fonksiyonumuza baktÄ±ÄŸÄ±mÄ±zda, iÅŸaretÃ§i olarak gelen parametremizin nasÄ±l kullanÄ±ldÄ±ÄŸÄ±nÄ± gÃ¶rÃ¼yoruz. Burada bizim iÃ§in Ã¶nemli olan kÄ±sÄ±m <em>Dispose</em> kÄ±smÄ±dÄ±r. &Ccedil;Ã¼nkÃ¼ burada <em>New</em> ile oluÅŸturduÄŸumuz ve iÅŸaretÃ§iye ait olan recordu hafÄ±zadan siliyoruz.</p><p
align="justify">Record iÅŸaretÃ§isi yerine normal record kullansa idik ve sonra da bunu parametre olarak geÃ§irirken pointer olarak geÃ§irse idik olmazmÄ±ydÄ±. Olurdu&#8230; &Uuml;stelik <em>New</em> ve <em>Dispose</em> rutinlerini de kullanmak zorunda kalmazdÄ±k. Ama, bu durumda boÅŸ yere hafÄ±zda yer iÅŸgal edecektik. &Ccedil;Ã¼nkÃ¼ parametre recordu sadece bir kerelik iÅŸimize yarayacak. Bu yÃ¼zden iÅŸimiz bitince <em>Dispose</em> ile hafÄ±zdan siliyoruz.</p><p
align="justify">Bu Ã¶rneÄŸimizi de Ã§alÄ±ÅŸtÄ±rÄ±p deneyebilirsiniz. AyrÄ±ca GÃ¶rev YÃ¶neticisi ile iÅŸlemciyi yÃ¼zde kaÃ§ kullandÄ±ÄŸÄ±nÄ± da gÃ¶rebilirsiniz. Tabi burada <em>Sleep</em> rutinini kullanmak yerine daha baÅŸka yapÄ±labilecek ÅŸeyler var ama ÅŸimdilik kafa karÄ±ÅŸtÄ±rmamak iÃ§in bunlarÄ± sonraya bÄ±rakÄ±yorum.</p><h1>SonuÃ§</h1><p
align="justify">Bu bÃ¶lÃ¼mÃ¼ burada noktalayalÄ±m. Gelecek bÃ¶lÃ¼mde kanallarÄ±n nasÄ±l birbirleri ile birlikte Ã§alÄ±ÅŸabileceÄŸini gÃ¶receÄŸiz. AyrÄ±ca Mutex&#8217;ler ve VCL ile kanal kullanÄ±mÄ± da gelecek bÃ¶lÃ¼mde gÃ¶receÄŸimiz konular arasÄ±nda olacak. BÃ¶ylece kanallar konusunda hiÃ§ bir ÅŸÃ¼pheniz, korkunuz kalmayacaÄŸÄ± gibi programlarÄ±nÄ±za da profesyonellik katacaksÄ±nÄ±z.</p><p
align="justify">Gelecek bÃ¶lÃ¼mde buluÅŸmak Ã¼midi ile&#8230; YorumlarÄ±nÄ±zÄ± ve eleÅŸtirilerinizi bekliyorum. Yine her zaman ki gibi sorularÄ±nÄ±zÄ± buradan yada Delphi TÃ¼rkiye <a
href="http://www.delphiturkiye.com/forum">forum</a>larÄ±ndan iletebilirsiniz</p><p
align="justify">Fatih Tolga Ata &copy; 2007</p><h2>Kaynaklar</h2><ul><li>Windows SDK YardÄ±m DosyasÄ±</li><li>Delphi 4 Unleashed, Charlie Calvert, Sams Pub., 1999</li></ul> ]]></content:encoded> <wfw:commentRss>http://www.diyezon.com/delphi-ile-threadkanal-kullanimi-bolum-1/feed/</wfw:commentRss> <slash:comments>25</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using memcached
Page Caching using memcached
Database Caching using memcached
Object Caching 871/1001 objects using memcached

Served from: www.diyezon.com @ 2012-05-20 08:51:14 -->
