Tag Archives: properties

Workflow Foundation 4.0’a Giriş

.NET 4.0 içerisinden Workflow Foundation (ayrıca WF 4.0 olarak anılır) workflow tabanlı uygulamaların geliştirilmesi için yeni bir örnek ifade eder.

Şimdi basit bir workflow oluşturma ile işe başlayalım. Visual Studio 2010’u çalıştırıp New Project linkine tıklayalım. Installed Templates’in altında, Visual C#’ın içerisinde, 4 adet farklı template’in var olduğunu göreceğiz. Buradan Windows Console Application’ı seçelim ve projemizin ismini HelloWF olarak adlandıralım.

HelloWF

Bu adım bize bir adet konsol uygulaması için Program.cs  ve Workflow1.xaml adında workflow’unuzdaki aktiviteleri tanımlayan dosyalar üretilir. XAML dosyası, iş akışı tanımınızdaki aktivite-türetilen elementleri içerir. Visual Studio 2010 size bu tür elementleri düzenlemeniz için grafiksel olarak bir arayüz imkanı tanır. Burada klasik bir VS 2010 arayüzünü görüyoruz. Sağ tarafta Solution Explorer, Properties, sol tarafta Toolbox, Server Explorer, alt tarafta ise Errors, Warnings ve Messages kısımlarını görmekteyiz (Tabi bu kısımların IDE içerisinde yerlerinin kişiden kişiye değişebileceğini unutmayalım.)

WF-IDE

Orta tarafta ise WF tasarım kısmını görüyoruz. Sağ altta zoom için gerekli olan seçenekleri ve Overview seçeneklerini görüyoruz. Zira Workflow Foundation içerisinde oluşturabileceğiniz aktiviteler çok büyük olabileceği için bu kontroller bize büyük resim içerisinde küçük resmi görebilmek için çok büyük avantaj sağlayacaklardır. Sol alt tarafta ise 3 adet kontrolümüz var. “Variables”, “Arguments” ve assembly dosyalarını içeren “Imports”. Variables kısmına tıkladığımızda var olan değişkenleri içeren bir pencere açılacaktır.

WF-Variables

Eğer oluşturduğunuz workflow’u bir sınıf olarak düşünürsek, variables kısmı sınıf üyeleri olarak düşünebiliriz. Bunlarla aktiviteler arasındaki paylaşılan verileri tutabilirsiniz. Bu değişkenleri isterseniz tüm workflow için, isterseniz belirli bir aktivite için tanımlayabilirsiniz. Arguments kısmı tıpkı değişkenler gibidir, farklı olarak workflow dışına veri geçisini sağlayabilirler. Bunları method parametreleri olarak düşünebiliriz. Not olarak; buradaki Direction kolonu, verinin nereye geçtiğini ya da workflow dışında nereye gönderildiğini gösterir.

WF-Arguments

 

~Workflow Tasarımı~

Workflow’u ilk oluşturduğumuzda tasarım kısmının boş olduğunu görürüz. Aktiviteleri sürükle bırak mantığı ile workflow’umuza ekleriz. Şimdi Workflow Foundation içerisinde küçük bir “Hello World” uygulaması yaratalım. Başlangıç için, Sequence aktivitesini tasarım alanına sürükleyip bunun içerisinde Writeline aktivitesini sürükleyelim. Diagram aşağıdaki şekilde görünecektir;

WF-Sequence-Writeline

Ayrıca Properties kısmı aşağıdaki şekilde görünür.

WF-Properties

Buradaki DisplayName özelliğini Hello şeklinde değiştirelim ki, bir çok Writeline aktivitemizin olduğu diagramlarda bu yapıları hatırlamamız kolaylaşsın. Ayrıca Text özelliğine “Hello, World!” kelimelerini giriş yapalım. Tasarım kısmında da aynı anda Writeline aktivitesinin içerisinde bu stringi görebiliriz. TextWriter özelliğini boş bırakabiliriz. Default olarak, bu text konsola yazılacaktır. Eğer spesifik bir uygulama yapmak isterseniz buraya TextWriter’dan türetilmiş sınıf yapılarını da yazabiliriz. Şimdi de Program.cs dosyamızda değişiklikler yapalım. Bu dosyayı ilk açtığımızda aşağıdaki şekilde görürüz;


using System;
using System.Linq;
using System.Activities;
using System.Activities.Statements;

namespace HelloWF
{

class Program
{
static void Main(string[] args)
{
WorkflowInvoker.Invoke(new Workflow1());
}
}
}

Statik WorkflowInvoker sınıfı Workflow1 sınıfı tarafından tanımlanmış workflow’u başlatır. Şimdi Main() methodumuzun içerisine aşağıdaki kodları ekleyelim;

Console.WriteLine(“ENTER to exit”);
Console.ReadLine();

Daha sonra projemizi F5 ile çalıştırdığımızda, aşağıdaki şekilde bir konsol çıktımız olur.

Hello, World!
ENTER to exit

Bu makalede Windows Workflow Foundation’a giriş kısmını anlatmaya çalıştım. Umarım bundan sonra WF 4.0 ile ilgili açıklayıcı makaleler yazabilirim.

C#’ta Fonksiyon Üyeleri

C#’ta çalıştırılabilir kod içeren üyeler genellikle sınıfın fonksiyon üyeleri olarak adlandırılırlar. Bir önceki yazıda belirttiğim konu olan methodlar konusu da aslında bir çeşit fonksiyon üyesidir. Aşağıda tablo Liste<T> olarak tanımlanmış bir generic sınıfın bir çok fonksiyon üyesi örneğini gösterir:

public class Liste<T> {
const int varsayılanKapasite = 4; Sabit
T[ ] elemanlar;
int sayaç;
Alanlar
public Liste (int kapasite = varsayılanKapasite ) {
elemanlar = new T[kapasite];
}
Yapıcı
public int Sayma {
get { return sayma; }
}
public int Kapasite {
get {
return elemanlar.Length;
}
set {
if (value < sayma) value = sayma;
if (value != elemanlar.Length) {
T[] yenielemanlar= new T[value];
Array.Copy(elemanlar, 0, yenielemanlar, 0, sayma);
elemanlar = yenielemanlar;
}
}
}
Özellikler
public T this[int index] {
get {
return elemanlar[index];
}
set {
elemanlar[index] = value;
OnChanged();
}
}
İndexleyiciler
public void Add(T item) {
if (sayma == kapasite) kapasite = sayma * 2;
elemanlar[sayma] = item;
sayma++;
OnChanged();
}
Methodlar
public event EventHandler Changed; Olaylar (Events)
public static bool operator ==(Liste<T> a, Liste<T> b) {
return Equals(a, b);
}
public static bool operator !=(Liset<T> a, Liste<T> b) {
return !Equals(a, b);
}
Operatörler
}
  • Yapıcılar (Constructors)

C# hem örnek hem de static yapıcıları destekler. Örnek yapıcılar, sınıfın ilk kullanımına hazırlamak için gerekli olan uygulama üyeleridir. Static yapıcılar, bir eylem gereken örnek sınıfın ilk yüklendiği zaman gerekli olan uygulama üyeleridir.

Bir yapıcı aynı bir method gibi tanımlanır fakat geri dönüş tipi olmamalı ve içerdiği sınıf ile aynı isme sahip olmalıdır. Eğer bir yapıcı, static anahtar kelimesi ile tanımlanmışsa o static yapıcıdır, aksi taktirde örnek yapıcı olarak adlandırılırlar.

Örnek yapıcılar aşırı yüklenebilir. Örneğin, Liste<T> adında bir sınıfın iki yapıcısı tanımlansın; birisini hiçbir parametre almayan, diğeri de bir adet int parametre alan. Örnek yapıcılar new operatörü kullanılarak çağırılırlar.


Liste<string> liste1 = new Liste<string>();
Liste<string> liste2 = new Liste<string>(10);

Diğer üyelerin aksine, örnek methodlar miras almazlar. Yani bir sınıfın kendi içinde tanıtılmış örnek yapıcısından başka bir örnek yapıcısı olamaz. Eğer bir sınıfın örnek yapıcısı yoksa, parametresiz boş bir örnek yapıcı otomatik olarak yaratılır.

Önemli: Yapıcılar tembel olmalıdırlar. En iyi pratik olarak yapıcılar içinde minimum iş yapılamıdır ki bu da basit bir şekilde argümanların daha sonra kullanımı için basitleştirmelidir. Örneğin; bir dosyanın ismini ya da o dosyanın yolunu veritabanı için tutmak istiyorsunuz ama dış kaynakları gerekli olmadığı sürece açmak istemiyorsunuz. Bu pratik, gerekli en az kaynağa erişimede emin olmak için yardımcı olur.

  • Özellikler (Properties)

C#’ta özellikler, alanların (fields) doğal uzantılarıdır. İkisi de ilişkilendirildikleri tiplerile birlikteki üyelerin isimleriyle, ilişkilendirildikleri alanların sözdizimi ile ve özelliklerle isimlendirilirler. Fakat, alanlardan farklı olarak, özellikler depolanmış bellek göstermezler. Bunun yerine, özelliklerin erişimcileri vardır ki onların değerlerini okuma ya da yazmada kullanılan ifadeleri belirtmede kullanılırlar.

Önemli: İyi bir uygulama tekniği olarak alanlara (özelliklerin verilerine) her zaman Getter ve Setter ile ulaşmak önerilir. Eğer Getter veya Setter’larınıza fonksiyonel işlevsellikler eklemek isterseniz, kodunuzu herhangi bir şekeilde kırmadan bunu kolaylıkla yapabilirsiniz.

Yukarıdaki anlatıma bir örnek verelim: Hiçbir zaman alanlarınızı (fields) public olarak tanımlamayın;


class İnek
{
public int Süt; // Kötü
}

Eğer belleğin yanında herhangi bir katman istemiyorsanız, bırakın derleyici sizin yerinize uygulasın;


class İnek
{
public int Süt {get; set;} // İyi
}

Bu sayede, istemci özelliğe Getter ve Setter’ı bağlar ve buna istinaden aşağıdaki şekilde derleyicinin uygulamasına etki edebilirsiniz;


class İnek
{
bool SüteSahip = false;
int Süt;
public int Süt {
get
{
if (!SüteSahip)
{
Süt = SütMakinesiUygula();
SüteSahip = true;
}
return Süt;
}
set
{
TersSütMakinesiUygula(value);
Süt = value;
}
}
}

Ayrıca, aşağıdaki kullanım ile hesaplanmış değer sizin programınızda kullanılır;


class İnek
{
public İnek()
{
Süt = SütMakinesiUygula();
}
public int Süt { get; private set; }
...
}

Bu durumda, özelliği tekrar hesaplıyoruz, ki neye ihtiyacımız olduğunu bilmediğimiz durumlarda bu gereksiz bir davranıştır.

Önemli: Özelliklere erişim tıpkı alanlara erişim gibi gözükür insanlara. Ve kişiler de doğal olarak alanlara erişim ile aynı performans göstereceklerini tahmin ederler. Eğer bir erişim belirgin bir iş ihtiyacı duyuyorsa (bir dosyadan okuma, veritabanında bir query çalıştırma gibi) bir method olarak açılmalıdır, bir özellik olarak değil. Bunu çağıranlar methodun daha fazla iş yaptığını düşünürler.

Aynı sebepten dolayı, özelliklere erişimde tekrarlı çağırımlar (koda müdahele etmeden) aynı değeri döndürmelidirler. DateTime.Now bu tavsiyeye uymayan örneklere sahiptir.

Bir özellik, bir alan ile aynı şekilde tanımlanır. İstisna olarak, noktalı virgülle bitirmek yerine Get ve Set erişimcilerini { ve } arasında kullanarak tanımsal biçimde alanlardan ayrılırlar. Hem Get hem de Set erişimcisine sahip özellikler okunur-yazılır (read-write) özellik, sadece Get erişimcisine sahip özellikler sadece okunur (read-only) ve sadece Set erişimcisine sahip özellikler de sadece yazılır (write-only) özellikler olarak tanımlanır.

Bir Get erişimcisi parametresiz bir method ve özellik tipini geri dönüş tipi olarak uygulayan bir method ile uyuşur. Belirlenen hedefin atamalar dışında, bir özellik bir ifadeyi referans ediyorsa, özelliğin Get erişimcisi, özelliğin değerini hesaplamada çağrılır.

Bir Set erişimcisi, value adında bir parametre içeren ve geri dönüş tipi olmayan bir method ile uyuşur. Bir özellik belirli bir atamayı ya da ++ ya da – gibi operandları referans ediyorsa, Set erişimcisi yeni değeri içeren bir argüman ile çağrılır.

Liste<T> sınıfı iki adet özellik tanımlar, Sayma ve Kapasite, sırasıyla sadece okunur ve okunur-yazılır özellikler. Aşağıdaki örnek bunların nasıl kullanıldığına bir örnektir:


Liste<string> isimler = new Liste<string>();
isimler.Kapasite = 100;   // Set erişimcisi çağrılır.
int i = isimler.Sayma;      // Get erişimcisi çağrılır.
int j = isimler.Kapasite;  // Get erişimcisi çağrılır.

Alanlarda ve özelliklerde benzer olarak, C# hem örnek özellikleri hem de static özellikleri destekler. Static özellikler static anahtar kelimesi ile tanımlanır, static anahtar sözcüğü kullanılmayan özellikler örnek özelliklerdir.

Bir özelliğin erişimcileri (Get ve Set) sanal (virtual) olabilirler. Eğer bir özellik tanımlaması virtual, abstract ya da override anahtar sözcüklerine sahipse, o özelliğin erişimcilerine uygular.

Önemli: Eğer bir sanal özellik, private erişimciye sahipse, o erişimci CLR içinde sanal olmayan methodtur ve türetilmiş sınıf içerisinde aşırı yüklenemez.

Özellikler aşağıdaki erişimcilere sahiptirler;

Statik değiştirici static
Erişim değiştirici public, internal, private, protected
Kalıtımsal değiştirici new, virtual, abstract, override, sealed
Yönetilemeyen kod değiştiricisi unsafe, extern
  • İndexleyiciler (İndexers)
    İndexleyiciler, diziler gibi, nesneleri indexleyebilen üyelerdir. Bir indexleyici, bir özellik ile aynı şekilde tanımlanır, tek fark olarak [ ] arasında parametre listesi hariç. Bu parametreler, indexleyicinin erişimcisi için uygundurlar. Özellikler gibi, indexleyiciler de read-write, read-only, write-only ya da bir indexleyici virtual tanımlanabilir.

Aşağıdaki List sınıfı string parametresi olan basit bir indexleyici tanımlamıştır;


List<string> isimler = new List<string>();
isimler.Add("Ülkü");
isimler.Add("Hülya");
isimler.Add("İlknur");
for (int i = 0; i < isimler.Count; i++) {
string s = isimler[i];
isimler[i] = s.ToUpper();
}

İndexleyiciler aşırı yüklenebilirler. Bunun anlamı sınıflar istedikleri uzunlukta parametre listeleri içeren indexleyici tanımlayabilirler.

  • Olaylar (Events)

Bir olay, sınıflara ya da nesnelere bildirim sağlanmasına olanak veren üyelerdir. Olaylar, tıpkı alanlar gibi tanımlanırlar. Fark olarak event anahtar kelimesi kullanılır ve tipi delegate tipi olmalıdır.

Jesse Liberty: Gerçekte, event anahtar sözcüğü sadece C#’ta delegate’in kullanılabilir olmasına bir yol göstericidir.

Chris Sells: event anahtar sözcüksüz, şunu yapabilirsiniz;


delegate void CalismaTamamlandi();
class Calisan
{
public  CalismaTamamlandi Tamamlandi; // Delegate alanı, bir event değil.

}
class  Patron
{
public void CalismaTamamlandi() { }
}
class Program
{
static void Main()
{
Patron Soner = new Patron();
Calisan isci = new Calisan();
isci.Tamamlandi += Soner.CalismaTamamlandi(); // Yapmak istediğiniz
isci.Tamamlandi = Soner.CalismaTamamlandi();  // Derleyicinin izin verdiği
}
}

Ne yazık ki, event sözcüğü ile birlikte, Tamamlandi() sadece delegate tipinde public bir alandır. Derleyici için de sorun oluşturmaz bu durum. Fakat event anahtar sözcüğünü eklediğimizde, += ve –= gibi operatörleri sınırlandırırsınız.


class Calisan
{
public event CalismaTamamlandi Tamamlandi;

}

isci.Tamamlandi += Soner.CalismaTamamlandi(); // Derleyici izin verir.
isci.Tamamlandi = Soner.CalismaTamamlandi(); // Derleyici hata verir.

Burada event sözcüğünün kullanımı sadece bir kere public bir alan oluşturmanın doğaln olmasıdır.Çünkü derleyici güvenli operatörlerin kullanımını daraltır.

Olay üyesi tanımlayan bir sınıf içerisinde, olaya delegate tipindeki bir alana erişimi gibi erişilebilir. Alan, olaylara eklenen olay tutucuları (event handler) temsil eden delegate’e bir referans saklar. Eğer herhangi bir event handler mevcut değilse, o alanın değeri null olur.

List<T> sınıfı basit bir olay üyesi olan Changed tanımlar ki bu yeni elemanların listeye eklenmesini gösterir. Changed olayı, OnChanged sanal methodundan kullanılır ki bu ilk önce olayın boş olup olmadığını kontrol eder. (Bunun anlamı hiçbir event handler’ın olmaması)

İstemciler olaylara olay tutucular (event handler) ile tepki gösterirler. Event handler’lar += operatörü ile eklenir ve –= operatörü ile silinebilirler. Aşağıdaki örnek, bir event handler’ın List<string>’in Changed olayına eklenmesini gösterir;


using System;
using System.Collections.Generic;

class Test
{
static int DegismeSayisi;
static void ListChanged(object sender, EventArgs e)
{
DegismeSayisi++;
}
static void Main()
{
List<string> isimler = new List<string>();
isimler.Changed += new EventHandler(ListChanged);
isimler.Add("Ülkü");
isimler.Add("Hülya");
isimler.Add("İlknur");
Console.WriteLine(DegismeSayisi); // Çıktı 3 olur.
}
}

Chris Sells: isimler.Changed += new EventHandler(ListChanged); yerine isimler.Changed += ListChanged; şeklinde bir kısaltma da kullanılabilir.

  • Yok Ediciler (Destructors)

Bir destructor, bir sınıf örneğini ya da nesnesini yoketmek için kullanılan uygulamaları içerir. Yokedicilerin parametreleri yoktur, erişim kelimelerine sahip değillerdir ve açık bir şekilde çağrılamazlar. Yokediciler otomatik olarak garbage collection zamanında çalıştırılırlar.

Garbage collector, nesnelerin ne zaman toplanacağına ve yokedicilerin ne zaman çalıştırılacağına imkan verir. Özellikle, yokedicilerin çağrılma zamanların rastgele değildir, ve yokediciler herhangi bir thread zamanında çalıştırılabilir. Bu nedenle, sınıflar yokedicileri  sadece başka çözümler olmadığı zamanda uygulamalıdırlar.

Önemli: Yokediciler bazen “Finalizer” olarak anılırlar. Bu isim aynı zamanda Garbage collector API’sinde de görünür; örneğin: GC.WaitForPendingFinalizers.