Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Sefer Algan
Sefer Algan
http://www.seferalgan.com
İletişme geçmek için tıklayın.
71 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: aslinda bulunan dinamik ilgili invoke isimli metodu namespace nesnenin nesneye reelproxy sinifi sinifindan tasarim yerine C# / VC#/.NET Sefer Algan
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : İleri
Kategori : C# / VC#/.NET
Yayınlanma Tarihi : 20.7.2009
Okunma Sayısı : 44413
Yorum Sayısı : 2     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 21.11.2024
Turhal Temizer
Mac OS/X Removing CUDA 21.11.2024
Burak Selim Şenyurt
Rust ile ECS Yaklaşımını Anlamak 21.11.2024
Burak Selim Şenyurt
Birlikte Rust Öğrenelim Serisi 21.11.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
TransparentProxy'nin Gizemli Yapısı ile Dinamik Proxy Yaratmak
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Değerli C#nedir?com okuyucuları; öncelikle uzun bir aradan sonra iş yoğunluğumdan dolayı yazamadığım yazılarıma yeniden başlamanın heyecanı içerisinde olduğumu belirtmek isterim. .NET platformunun sunduğu hemen hemen bütün yapıların C# seviyesinde tip(type) bakımından bir açıklaması vardır. Ancak bazı öyle kavramlar vardırki tip kavramından yola çıkarak açıklayamayız. Örneğin her sınıfın object’ten türemesi, delegate yapısında BeginInvoke ve EndInvole yapısının olması, Remoting altyapısında bulunan TransparentProxy gibi. Bu gibi yapılar genellikle derleyici ile doğrudan ilişkili değil çalışma zamanı ve CLR ile ilgili olmaktadır. İşte bu makalemde sizlere proxy tasarım kalıbı ile doğrudan ilgili olan .NET’in sunduğu dinamik proxy tasarım kalıbından bahsedeceğim.

Bu yazımın anlamlı olabilmesi için öncelikle GoF tasarım kalıplarından olan Proxy ve kullanım alanlarından bahsetmek istiyorum. Proxy kelime anlamı olarak temsilci demektir. GoF kalıbı olarak ise bir nesnenin görevini başka bir nesne yardımıyla yerine getirmek anlamında kullanılır. Örneğin iş nesnelerinize ait metotların tamamının çağrılmadan önce belirli güvenlik kontrollerinden geçirmek isterseniz, yada kritik olarak işaretlediğiniz operasyonların çağrılmasından önce bir takım kayıtlar (log) tutmak isterseniz, yada belirli fonksiyon gruplarının merkezi bir noktadan yönetilmesini sağlamak isterseniz aslında yapmanız gereken iş nesneleriniz için bir proxy(vekil yada temsilci) tanımlamaktır. Pratik olarak .NET içerisinde bir çok yerde proxy sınıfları kullanılmıştır. Bunlardan en önemlisi Remoting altyapsında bulunan proxy yapısıdır. Proxy sınıfları daha çok nesnenin yaratılması güç olan sınıflarda işlemleri basitleştirmek ve kolay yönetebilmek amacıyla yapılır. Son zamanlarda adını sıkça duyguğumuz AOP (Aspect Oriented Programming) metodolojisinin .NET’te uygulanabilmesi içinde yine Proxy sınıflarından faydalanıyoruz. AOP’a göre çapraz kesen ilgi (cross cutting concerns) dediğimiz loglama (logging), ön bellekleme (caching), güvenlik(security), izleme (trace), istisna yönetimi (exception handling) ve doğrulama (validation) gibi rutin işlemlerin iş sınıflarından (bussiness classes) tamamen ayrılması ve bağımsızlaştırılması gerekir. Ve bu ilgilerin kod içerisine gömülmesi derleme aşamasından bağımsız yapılmalıdır. Bu kural AOP’un en temel kuralıdır. Ancak AOP’un tam olarak platformalarda uygulanabilmesi için derleyicilerin bu yeni modele göre geliştirilmesi gerekir. C# dünyasında şu anda böyle bir oluşum olmadığından AOP gerçek manada uygulayamıyoruz ancak çeşitli yollarla (reflection, attribute , proxy vs ) simule edebiliyoruz. Java dünyasında ve .NET dünyasında AOP mimarisini uygulayan AspectJ isimli bir altyapı bulunmakta. Konumuz AOP olmadığı için daha fazla detaya girmeyeceğim ancak sonraki makalelerimde AOP’a detaylı girmeyi planlamaktayım.

Tekrar konumuza dönecek olursak; AOP benzeri bir modeli makalemizinde konusu olan TransparentProxy sayesinde gerçekleştirebiliyoruz. Geçtiğimiz aylarda yayınlanan Enterprise Library 3.0 içerisinde bulunan Policy Injection Application Block (PIAB) içerisinde de yine bu yaklaşım mevcuttur. Proxy kalıbı aynı zamanda mevcut bir altyapıya kendi bileşenlerimizi entegre etmek amacıylada kullanılabilir. Örneğin Oğuz Yağmur’un Debugger ile ilgili yazdığı yazıda bulunan DebugerTypeProxy sınıfı buna bir örnek olarak gösterilebilir. .NET içerisindeki bu sihirli mekanizmadan bahsetmeden önce GoF tasarım kalıplarından Proxy kalıbı hakkında temel bilgi ve uygulama vermek istiyorum.

GoF, Proxy kalıbını tanımlarken statik bir proxy sınıfından bahsetmiştir. Yani asıl ulaşmak istediğimiz nesneye başka bir nesne yardımıyla erişiyoruz. Proxy tasarım kalıbının genel sınıf diyagramı aşağıdaki gibi gösterilebilir.


Şekil 1 : Proxy tasarım kalıbının sınıf diyagramı.

Şemadan dan görüleceği üzere aynı arayüzü uygulayan gerçek ve temsilci nesneler mevcuttur. İstemci asıl nesneye (reel object) ulaşmak yerine aynı arayüzü uygulayan temsilci sınıfı kullanmaktadır. Tabi bunun olabilmesi için proxy sınıf içerisinde gerçek nesnenin yaratılması gerekmektedir.

Bu aşamada sınıf diyagramını basit bir şekilde kod ile örneklendirmekte fayda var. Bunun için basit bir Bank sınıfında bulunan metotları Proxy yardımıyla kullanımını görmüş olacağız.

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms; namespace GoFProxyTest
{
      public interface IArayuz
      {
            void EftYap(string kimden,string kime,int tutar);
            void HavelYap(string kimden, string kime, int tutar);
      }

      public class BankProxy : IArayuz
      {
            Bank _realBankObject;

           public BankProxy()
           {
                if (_realBankObject == null)
                     _realBankObject = new Bank();
                }

           public void EftYap(string kimden, string kime, int tutar)
           {
                //validasyon işlemini gerçekleştir
                //loglama işlemini yap
                //güvenlik kontrolünü yap
                _realBankObject.EftYap(kimden, kime, tutar);
                //bir takım istatistiksel verileri kaydet
            }

            public void HavelYap(string kimden, string kime, int tutar)
            {
                  //validasyon işlemini gerçekleştir
                  //loglama işlemini yap
                  //güvenlik kontrolünü yap
                  _realBankObject.HavelYap(kimden, kime, tutar);
                  //bir takım istatistiksel verileri kaydet
             }
     }

     public class Bank : IArayuz
     {
            public Bank()
            {

            }

          public void EftYap(string kimden, string kime, int tutar)
          {
               MessageBox.Show("eft işlemi");
          }

          public void HavelYap(string kimden, string kime, int tutar)
          {
               MessageBox.Show("havale işlemi");
          }
     }

     public class Client
     {
          public static void Main()
          {
               BankProxy bank = new BankProxy();
               bank.EftYap("ali", "veli", 10);
          }
     }
}
Yukarıdaki örnek kod kafanızda bir çok soru işaretine neden olduğunu görüyor gibiyim. Evet, isterseniz bu tarz bir proxy (aslında statik proxy de denilebilir) kalıbının avantajları ve dezavantajlarını madde madde yazalım ve sonraki bölümlerde dezavantajına dinamik proxy ile cevap bulalım.

Statik proxy tasarım kalıbının dezavantajları;

  • Her sınıf için ayrı bir proxy sınıfının yazılması ki bu büyük bir problemdir.
  • Tutarlılık için her sınıfın arayüzünün çıkarılması (zorunlu değil)
ve avantajları;

  • İş nesnesine ait erişimi kontrol altına almış oluyoruz.
  • Asıl iş nesnesine erişmeden önce yada sonra bir takım ek işlemler yapabiliyoruz.
  • Asıl iş nesnemize dokunmadan ek özellikler eklemiş oluyoruz. Dağıtık(distributed) mimaride önemli bir konudur.
  • Tip güvenliği korunur (proxy gerçek nesne ile aynı arayüze sahiptir). Bu durum programcı için önemlidir.
Yukarıdaki listeden de görüleceği üere proxy kalıbını bu şekile kullanmayı bir kaç özel istisna durum dışında pek tercih edilmeyeceği görülmektedir. Çünkü her iş nesnesi için yeni proxy sınıfları yaratmak gerekiyor. Bu durum itici ve yorucu bir iştir. Bu yüzden dinamik proxy sınıfları gündeme gelmiştir. Yazımızın ana konusuda işte dinamik proxy sınıflarının programcının üretkenliğinide düşürmeyecek şekilde .NET ile nasıl yapılacağıdır. İşte bu işi yapacak olan .NET Framework içersinde bulunan ReelProxy ve TransparentProxy isimli gizemli sınıflardır.

TransparentProxy ve ReelProxy sınıflarının çalışma biçimini incelemeden önce bu sınıflar olmadan dinamik proxy üretilebilirmi sorusuna cevap arayalım? Aslında üretirbilir. Cevabı ise çok basit: reflection kütüphanesi ve generic mimari ile. Örneğin aşağıdaki gibi bir tanımı içerek bir DinamikProxy nesnesi ile her sınıf için ortak çalışabilecek bir proxy nesnesi yaratılabilir.

DynamicProxy<Bank> proxyBank = new DynamicProxy<Bank>();

proxyBank.OperateMethod("HavaleYap","Ali","Veli",3);
Yukarıdaki gibi bir Proxy yaratıldığında bu sefer proxy sınıfında gerçek nesneye ait üye elemanlar ancak çalışma zamanında (runtime) çözülebileceği için performans problemi yaratacaktır. Aynı zamanda programcı kod yazarken metot ve üye eleman güvenliğini tam sağlayamama riski ile karşı karşıya kalacaktır. Buda kod yazmayı bir hayli zorlaştırağı için malesef tercih edilemeyecek yöntemler arasında yerini alacaktır. Tabi yine istisnalar kaideyi bozmaz. Mecburen tercih edilen durumları yok sayıyoruz.

İşte tam bu durumda imdadımıza .NET içerisinde bulunan TransparentProxy ve ReelObject yetişiyor. Şimdi 3 farklı yöntemle gerçek dinamik proxy sınıflarını nasıl üreteceğimizi inceleyeceğiz.

TransparentProxy ve ReelProxy

System.Runtime.Remoting.Proxies isim alanınında bulunan ReelProxy nesnesinden türeyen bir sınıf ile herhangi bir nesneye ait metodunun çağrımına müdahale edebilirsiniz. ReelProxy içerisinde Invoke isimli metot override edilerek asıl metot çağrılmadan önce herhangi bir işlemi gerçekleştirebilirsiniz. Bu işlem için elbette yine Reflection kullanacağız.

TransparentProxy ise herhangi bir nesnenin yerine geçen saydam bir sınıftır. Yani programcı kod yazma aşamasında HavaleYap isimli fonksiyonu çağıracaktır ancak aslında çalışma zamanında HavaleYap fonksiyonu çağrılmayacaktır. Bunun yerine ReelProxy sınıf içerisinde bulunan Invoke isimli fonksiyon devreye girilecektir. Invoke fonksiyonu içerisinde metot çağrımından önce ve sonra istenilen işlem icra edilebilir. Bu işlemi yapabilmek için ReelProxy sınıfı içerisinde bulunun GetTransparentProxy isimli metot çağrılarak nesne yaratılmalıdır. Bu nesne aslında object tipinde olmasına rağmen saydamlığından ötürü biz object ile uğraşmayız direkt olarak asıl nesneymiş gibi erişebiliriz. Bu durum C# dil kuralları ile açıklamak mümkün değildir. TransparentProxy nesneleri derleyici ve CLR tarafından özel işleme tabi tutulurlar. Bunu bir örnekler aşağıda göstereceğim.

Yukarıdaki paragrafı şematik olarak göstermek istersek en basit dinamik proxy yapısını kavramış oluruz.


Şekil 2 - TransparentProxy kullanılarak ve kullanılmayarak gerçek nesneye erişim sınıf diyagramları.

Yukarıdaki şemadan anlaşılacağı gibi TransparentProxy ile saydam proxy yaratabilmenin şartı gerçek sınıfın MarshalByRefObject sınıfından türeme zounluluğudur. (MarshalByRefObject sınıfı System isim alanında bulunur.)

Buna göre adım adım hangi sınıfları yazmamız gerektiğini inceleyebiliriz.

Öncelikle iş nesnemizi çok sade bir şekilde yazabiliriz. Çünkü iş nesnemizin çalışması için gereken doğrulama, güvenlik, caching ve loglama gibi ayrık işlemler transparentProxy tarafından gerçekleştirilecektir.

BankOperationObject.cs

using System;
using System.Windows.Forms;

namespace WindowsApplication1.Metot1
{
      public class BankOperationObject : MarshalByRefObject
      {
            public void HavaleYap(int from, int to)
            {
                  MessageBox.Show("Havale yapıldı");
            }
      }
}
Şimdi ise BankOPerationObject isimli sınıfa erişmeye yarayacak ReelProxy sınıfını oluşturabiliriz. Bunun Proxy sınıfımızı System.Runtime.Remoting.Proxies isim alanında bulunan ReelProxy isimli sınıfta türetmemiz gerekecektir.

ProxyObjectCreator.cs
using System;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
using System.Windows.Forms;

namespace WindowsApplication1.Metot1
{
      public class ProxyObjectCreator : RealProxy
      {
            private BankOperationObject _realObject;

            public ProxyObjectCreator(BankOperationObject realObject)
                   : base(typeof(BankOperationObject))
            {
                  this._realObject = realObject;
            }

            public static BankOperationObject CreateObject()
            {
                  BankOperationObject reelInstance = new BankOperationObject();
                  ProxyObjectCreator proxyObject = new ProxyObjectCreator(reelInstance);
                  BankOperationObject transparentProxyObject = (BankOperationObject)proxyObject.GetTransparentProxy();
                  return transparentProxyObject;
            }

            public override IMessage Invoke(IMessage msg)
            {
                  IMethodCallMessage message = (IMethodCallMessage)msg;
                  if (message != null)
                  {
                        MessageBox.Show(message.MethodName + " metodu çağrılmak üzere. Biz araya girdik çağrılmadan önce");

                        this._realObject.HavaleYap((int)message.InArgs[0], (int)message.InArgs[1]);

                        ReturnMessage retVal = new ReturnMessage(null, null, 0, message.LogicalCallContext, message);

                        return retVal;
                  }
                  return null;
            }
      }
}
Yukarıda bulunan kod Proxy sınıfını incelediğinizde gerçek nesneye ait bir referans bulunmaktadır. Ancak gerçek nesnenin yaratılma işlemi kendimize ait static CreateObject() isimli metot ile yaratmamız gerekiyor. Bu metodun geri dönüş değer BankOperationObject olmasına rağmen biz metotdan geriye GetTransparentProxy() sınıfın döndürdüğü object nesnesini aktarabiliyoruz. Bu işlemi tür dönüştürme işlemi ile legal hale getiriyoruz. İstemci bu proxy üzerinden HavaleYap yada farklı bir metot çağırdığında aslında nesnenin ilgili metodu çağrılmayacak direkt olarak ReelProxy içerisindeki Invoke isimli metot devreye girecektir. Burada yapmak istediğimiz herşeyi yapıp metodu çağırabileceğimiz gibi bir exception da üretebiliriz. Örneğin yetkisiz bir çağrım ifadesi oluşursa metodu çağırmakayabiliriz.

Not : IMessage tipi Invoke sınıfına gelen çağrım ifadesi ile ilgili bilgiler içermektedir. Bu bilgileri kullanarak aslında gerçek metodun hangi parametrelerle çağrıldığını ve hangi üye eleman kullanılarak çağrıldığını algılayabiliyoruz. Aynı zamanda metodun geri dönüş değeride yine bu tip kullanılarak hazırlanmaktadır. Invoke metodu içerisindeki kullanım gayet açık olduğu için bu tip ile ilgili fazla detaya girmiyorum.

Sıra istemci koduna geldi. İstemci kodumuz artık BankOperationObject sınıfını direkt olarak kullanmak yerine ProxyObjectCreator isimli sınıfımızın static olan CreateObject isimli metodunu çağırarak nesne yaratacaktır

istemci.cs
private void button1_Click(object sender, EventArgs e)
{
        BankOperationObject obj = ProxyObjectCreator.CreateObject();

        obj.HavaleYap(4, 5);
}
Dikkat ederseniz yukarıdaki kod bloğunda HavaleYap metodu çağrılmasına rağmen TransparentProxy sayesinde aslında bu fonksiyon çağrılmayacaktır. Bunun yerine çalışma zamanında ReelProxy’de bulunan Invoke metodu devreye girecektir. Yani biz aslında metot çağrımına müdahale etmiş olduk. Metodu çağırmadan önce daha önce bahsetmiş olduğumuz çapraz kesen ilgilerin hepsini Invoke metodu içerisinde gerçekleyebiliriz.

İstemci kodunun çalışma zamanındaki nesnel yapısını gördüğümüzde aslında ne demek istediğimi daha iyi anlayacaksınız.


Gördüğünüz gibi obj aslında kendimize ait bir tip olmasına rağmen çalışma zamanında TransparentProxy tipi olarak çözümlenmiştir. Bu bize kod yazma aşamasında büyük bir saydamlık sağlamaktadır. Yani tip üye bilgilerini kaybetmeden dinamik proxy yaratmış oluyoruz.

Bu yöntem ile bir önceki yöntemde bulunan tip güvenliğini kaybetme dezavantajını bertaraf etmiş olduk. Ancak bu örnek ile hala her sınıf için proxy nesne yaratma handikapından kurtulamadık. Bu sorunuda biraz sonra aşacağız.

Bu yöntem ile birlikte yeni bir sorunla daha karşı karşıyayız. Dinamik proxy yaratabilmek için iş nesnemizi (BankOperationObject) illa MarshalByRefObject sınıfından mı türetmemiz gerekiyor? Aslında cevabımız hem evet hem hayır. Evet; çünkü istersek iş nesnelerine ait interface(arayüz) kullanarakta bu örneği yapabiliriz. Bir sonraki örneğimiz bu işlemi MarshalByRefObject kullanmadan gerçekleştireceğiz.

TransparentProxy ve ReelProxy (2.Yöntem)

Bu yöntem iş nesnelerimizin proxy ile yönetilcek arayüzlerini bir interface olarak tanımlamamız gerekiyor. Bu amaçlar BankOperationObject sınıfımızı aşağıdaki gibi değiştirmemiz gerekiyor.

using System;
using System.Windows.Forms;

namespace WindowsApplication1.Metot2
{
      public interface IBankOperation
      {
            void HavaleYap(int from, int to);
      }

      public class BankOperationObject : IBankOperation
      {
            public void HavaleYap(int from, int to)
            {
                  MessageBox.Show("Havale yapıldı");
            }
      }
}
İkinci aşamada ise ReelProxy sınıfından türeteceğimiz sınıf içerisinde gerçek nesne yerine IBankOperation arayüzünü kullanmamız gerekiyor. Bu amaçla ProxyObjectCreator sınıfımızı aşağıdaki gibi değiştirmemiz gerekiyor.

using System;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
using System.Windows.Forms;

namespace WindowsApplication1.Metot1
{
      public class ProxyObjectCreator : RealProxy
      {
            private IBankOperation _realObject;

            public ProxyObjectCreator(IBankOperation realObject)
                   : base(typeof(IBankOperation))
            {
                  this._realObject = realObject;
            }

            public static IBankOperation CreateObject()
            {
                   BankOperationObject reelInstance = new BankOperationObject();
                   ProxyObjectCreator proxyObject = new ProxyObjectCreator(reelInstance);

                   IBankOperation transparentProxyObject = (IBankOperation)proxyObject.GetTransparentProxy();
                   return transparentProxyObject;
            }

            public override IMessage Invoke(IMessage msg)
            {
                  //... Bu metodun içeriği değişmemiştir..
            }
      }
}
Bu durumda istemci kodumuzda aşağıdaki gibi değiştirilmek zorunda.

private void button1_Click(object sender, EventArgs e)
{
        IBankOperation obj = ProxyObjectCreator.CreateObject();

        obj.HavaleYap(4, 5);
}
2. yöntemle kazandığımız tek şey MarshalByRefObject sınıfından kurtulmak oldu. Hala her sınıf için proxy yazma zahmetinden kurtulamadık. Bu aşamada ProxyObjectCreator sınıfımızı geliştirmemiz lazım. Şükür ki .NET 2.0 ve C# 2.0 ile birlikte Generic mimarisi ile şablon türler tanımlayabiliyoruz. 3. yöntemde ise bu sorunuda bertaraf etmek için ProxyObjectCreator isimli sınıfımızı iş sınıfların tamamen soyutlayacağız. Bunun için Reflection ve generic mimarisine hakim olmamız lazım. Generic mimarisi ve reflection kütüphanesi ile ilgili sitemizde bir çok makale bulunmaktadır. Arama bölümünden bu yazılara erişebilirsiniz.

Generic Mimari ile TransparentProxy ve ReelProxy (3.Yöntem)

Bu yöntemde iş sınıflarımız değişmeyecektir. (Tek koşul aynı remoting mimarisinde olduğu gibi MarshalByrefObject sınıfından türetilmesidir.) Yeni yazacağımız generic Proxy sınıfı ile her türlü iş nesneimize proxy yarıdmıyla dinamik bir şekilde erişme şansına sahip olacağız. Dolayısıyla iş nesnelerimiz aşağıdaki gibi olabilir.

using System;
using System.Windows.Forms;

namespace WindowsApplication1.Metot3Generic
{
      public class BankOperationObject : MarshalByRefObject
      {
            public void HavaleYap(int from, int to)
            {
                  MessageBox.Show("Havale yapıldı");
            }
      }

      public class BankCriticLoader : MarshalByRefObject
      {
            public void MakeCriticLoad()
            {
                  MessageBox.Show("kritik yükleme yapıldı");
                  return 0;
            }
      }
}
Sıra en önemli sınıfımızı tasarlmaya geldi. Dikkat ederseniz bu sınıf içerisinde artık RealObject yerine sınıf bazında tanımlanan TObject isimli bir şablon tür kullanılmıştır.Her sınıfın bir yapılandırıcısı olma zorunluluğunu koyduğumuza dikkat ediniz. Bu proxy içerisinde gerçek nesnelerin yaratılması için zorunludur. Kısaca özetlemek gerekirse MarshalByrefObject sınıfından türeyen ve içinde bir adet varsayılan yapıcı metot içeren her iş nesnesi bu proxy sınıfı yardımıyla temsil ettirilebilecektir.

GenericProxyCreator.cs
using System;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
using System.Windows.Forms;

namespace WindowsApplication1.Metot3Generic
{
       public class GenericProxyCreator<TObject> : RealProxy where TObject:new()
       {
              private TObject _realObject;

              public GenericProxyCreator(TObject realObject) : base(typeof(TObject))
              {
                     this._realObject = realObject;
              }

              public static TObject CreateObject()
              {
                     TObject reelInstance = new TObject();

                     GenericProxyCreator<TObject> proxyObject = new GenericProxyCreator<TObject>(reelInstance);

                     TObject transparentProxyObject = (TObject)proxyObject.GetTransparentProxy();

                     return transparentProxyObject;
              }

              public override IMessage Invoke(IMessage msg)
              {
                     //Bu örnek gelen çağrımın bir metot olduğu varsayımı altında yapılmıştır.
                     //Eğer çağrım bir Property ise ona göre bu kodu değiştirmek gerekir.Yani set_ ve get_ önekleri ile metodu dinamik bir şekilde çağırmak gerekir.

                     IMethodCallMessage message = (IMethodCallMessage)msg;

                     if (message != null)
                     {
                            MessageBox.Show(message.MethodName + " metodu çağrılmak üzere. Biz araya girdik çağrılmadan önce");

                            object methodRetval =message.MethodBase.Invoke(_realObject, message.InArgs);

                            ReturnMessage retVal = new ReturnMessage(methodRetval,null, 0, message.LogicalCallContext, message);

                            return retVal;
                     }
                     return null;
             }
      }
}
İstemci kodumuz ise aşağıdaki şekillerde olabilecektir. Dikkat ederseniz her türlü nesneyi rahatlıkla proxyGenerator sınıfında kullanabiliyoruz.

private void button3_Click(object sender, EventArgs e)
{
       BankOperationObject obj = GenericProxyCreator<BankOperationObject>.CreateObject();
       obj.HavaleYap(4, 5);

       BankCriticLoader obj2 = GenericProxyCreator<BankCriticLoader>.CreateObject();
        obj2.MakeCriticLoad();
}
Generic mimari üzerine inşa ettiğimiz Proxy sınıfı TransparentProxy yardımıyla nihayet istediğimiz kıvama gelmiştir. Bu aşamadan sonra yapmak gereken AOP’un bahsettiği çapraz kesen ilgileri bir şekilde uygulamak. Örneğin iş nesnelerimizdeki üyelere çeşitli attribute’lar koyarak gereken cache,güvenlik, doğrulama vs gibi işlemleri organize edebiliriz. Tabi bu niteliklerin (attribute) Invoke metodunun içerisinde ele alınması lazım.

Buna basit bir örnek vermek gerekirse;

using System;
using System.Windows.Forms;

namespace WindowsApplication1.Metot3Generic
{
      public class BankOperationObject : MarshalByRefObject
      {
            [CheckSecurity]
            [LogMessage]
            public void HavaleYap(int from, int to)
            {
                  MessageBox.Show("Havale yapıldı");
            }

            [CacheReturnValue]
            [DisposeAfter]
            public DataTable GetUserInfo(int id)
            {
                    return....
            }
      }
}
Not : Bu örnekte kullanılan nitelikler hayali niteliklerdir. Bunların programcı tarafından yazıldığı ve ReelProxy’nin Invoke metodunda ele alındığı varsayılmaktadır. Bu örnek TransparentProxy’nin kullanımına gerçek örnek olması açısından verilmiştir.
Gördüldüğü gibi TransparentProxy ile iş nesneleri rutin olarak kullanılan çapraz kesen ilgilerden bağımsız bir hale getirilebilir. Buda AOP’un temel ilkesine bizi oldukça yaklaştırmaktadır. Ancak AOP bundan ötesinide sunmaktadır elbette. İlerleyen yıllarda C# dili ve CLR, AOP ilkelerine göre değiştirilirse belkide bu tarz işlemlere bile gerek kalmadan yapabileceğiz.

Son olarak bütün bu TransparentProxy mekanizmasını ve nitelik tabanlı (attribute based) AOP modelini içeren komple çözümü Enterprise Library 3.0’da bulunan Policy Injection Application Block (PIAB) içerisinde bulabilirsiniz.

Umarım .NET’in gizemli bir kapısını sizlere aktarabilmişimdir.

Makalede geçen örnek uygulamaları indirmek için tıklayınız.


Kaynaklar
- MSDN Dökümanları

Sefer Algan
sefer.algan a-t btakademi.com
algans a-t csharpnedir.com

Makale:
TransparentProxy'nin Gizemli Yapısı ile Dinamik Proxy Yaratmak C#, Visual C# ve .NET Sefer Algan
  • Yazılan Yorumlar
  • Yorum Yaz
OCA
3
2010
slmlar AOP konusundaki makalenizi bekliyorum. Sefer hoca daha fazla makale yazmanızı rica ediyorum.
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor