Serdar YILMAZ / Software Developer
Bizimkisi Bir “Bug” Hikayesi...
Akbank Bankacılık Merkezi
Serdar Yılmaz C# – Katmanlı Mimaride Generic’ler

C# – Katmanlı Mimaride Generic’ler

.net
Generic sınıfların, metotların ve arayüzlerin nasıl oluşturulduğundan (bkz: Generic Sınıflar, Metotlar ve Arayüzler) ve ne tür kısıtlar eklenebileceğinden (bkz: Generic Kısıtlar) bir önceki yazılarımızda bahsetmiştik. Bu içerikte ise Generic’lerin gerçek bir projede ne amaçla ve nasıl kullanılabileceğini olabildiğince yalın ve anlaşılır bir şekilde aktarmaya çalışacağım.

Örnek Senaryo: Müşteri, Ürün ve Kategori bilgilerini tutan Customer, Product ve Category isimli sınıflarımız olduğunu farz edelim. Müşterileri, Ürünleri ve Kategorileri listeleyecek, arama ve silme yapabilecek Manager sınıfları, Generic’leri kullanarak oluşturmaya çalışalım.

Müşterinin Id, isim ve adres bilgilerini tutan Customer isimli bir sınıfımız olsun.

Müşterileri listeleyecek, silecek ve müşteri listesinde arama yapabilecek metotlara ihtiyacımız olduğunu farz edelim. Bu ihtiyaçları ICustomerManager arayüzünde bildiriyoruz.

ICustomerManager arayüzünde bildirimini yapmış olduğumuz metotları, CustomerManager isimli sınıf içerisinde tanımlıyoruz. CustomerManager sınıfında arama, silme ve listeleme işlemlerini _customers koleksiyonu üzerinde yapmaktayım, sizler geliştireceğiniz uygulamalarda bu işlemleri veritabanı üzerinde yapabilirsiniz.

Şimdi ise Ürün ve Kategori bilgilerini tutan Product ve Category sınıflarına ihtiyacımız olduğunu düşünelim.

Müşterilerde olduğu gibi Kategorilerde ve Ürünlerde de listeleme, silme ve arama işlemlerini yapacak metotlara ihtiyacımız olacaktır. Bu ihtiyaçları IProductManager ve ICategoryManager arayüzlerinde bildiriyoruz.

Oluşturmuş olduğumuz arayüzleri inceleyecek olursak; her üç arayüzde de(ICustomerManager, IProductManager, ICategoryManager) List, Find ve Remove metotlarının bildiriminin yapıldığını ve sadece parametre türlerinin ve metotların geri dönüş türlerinin farklılık gösterdiğini görebiliriz. O halde Generic bir arayüz oluşturup, parametre türlerini ve metotların geri dönüş türlerini parametrik hale getirebiliriz.

Generic IRepository<T> arayüzü sayesinde, Manager sınıflar (CustomerManager, ProductManager, CategoryManager) için oluşturduğumuz arayüzlerin (ICustomerManager, IProductManager, ICategoryManager) hepsinde aynı metotların bildirimini yapmak zorunda kalmayacağız. Artık tüm Manager sınıflarda bulunması gereken ortak metotların bildirimini IRepository<T> arayüzünde yapacağız. Manager sınıfa özgü olan metotların bildirimini de o Manager sınıf için oluşturduğumuz arayüzün içerisinde yapacağız.

Kod kalabalığını arttırmamak için yukarıda ki kod bloğunda Product ve ProductManager sınıflarına yer vermedim. Yukarıdaki kod bloklarını inceledikten sonra aklınıza şöyle bir soru gelebilir; ICustomerManager ve ICategoryManager arayüzlerinin içerisinde ekstradan herhangi bir metot bildirimi yapılmadı, o halde neden tanımlama gereği duyuldu, neden IRepository arayüzü direkt Manager sınıflara implement edilmedi ?

IRepository<T> arayüzü içerisinde tüm Manager sınıflarda bulunması gereken metotların bildirimi yapılır. Ancak Manager sınıfların içerisinde IRepository<T> arayüzünde bildirilmiş metotların haricinde kendilerine has metotlar da bulunabilir. Örneğin CustomerManager sınıfı içerisinde müşterilerin adres bilgisini döndüren bir metot olabilir. Eğer IRepository<T> arayüzü içerisinde bu metodun bildirimini yapmış olsaydık, bu metodu CategoryManager içerisinde de gerek olmamasına rağmen tanımlamamız gerekirdi. Bu yüzden tüm Manager sınıflar için ortak olan metotlar IRepository<T> arayüzünde bildirilir, Manager sınıfa özel olan metotlarda o Manager sınıfa özel olarak oluşturulmuş arayüzde bildirilir.

Son olarak; dikkat edecek olursak, IRepository<T> arayüzüne herhangi bir kısıt konulmamış durumda. Bu yüzden arayüze veri tipi olarak hem değer tipliler hem de referans tipliler gönderilebilir. Ancak biz arayüze sadece Customer ve Category gibi Entity’lerin gönderilmesini istiyoruz. O halde IRepository<T> arayüzüne bir kısıt eklememiz gerekiyor.

IEntity adında bir arayüz oluşturduk ve where T : class, IEntity kısıtı ile IRepository<T> arayüzüne sadece IEntity arayüzü implement alan referans tiplilerin gönderilmesine izin verdik.  IRepository<T> arayüzüne Customer ve Category sınıflarının gönderilmesini istediğimizden IEntity arayüzünü bu sınıflara implement ediyoruz. Kod bloklarının son hali;

Serdar YILMAZ


Bu İçeriği Arkadaşlarınızla Paylaşmak İster misiniz?

Bir Yorum Yapın