C # 5 Caller Info Attributes Kullanımı ve Eski Versiyonlar İçin Bir Yöntem Önerisi

Merhabalar.

C# 5’te(yani .NET Framework 4.5’ta) gelen Caller Info özellikleriyle herhangi bir metodu nereden çağırdığımıza dair bilgilere erişebiliyoruz.

Bu da özellikle loglama ve izleme(örneğin SQL Server Profiler kullanımı) işlemlerinde büyük fayda sağlıyor.

Syntax şu şekilde :

public void NeredenGeldim(string parametre, 
                                             [CallerMemberName]string cagiranMetodAdi = "", 
                                             [CallerFilePath]string cagiranDosyaYolu = "", 
                                             [CallerLineNumber]int cagiranSatirNumarasi = 0)

Bu attributeleri şu şekilde açıklayabiliriz:
CallerMemberName: Bu metodun hangi metoddan çağırıldığı bilgisini,
CallerFilePath: Bu metodun çağırıldığı dosyanın dosya yolunu,
CallerLineNumber: Bu metodun çağırıldığı satır numarasını almamızı sağlar.

Örneklere başlamadan önce NOT: Resimleri üzerlerine tıklayarak büyütebilrsiniz.

Şu örneği inceleyerek oldukça basit bir kullanımı olduğunu görebilirsiniz:

static void Main(string[] args)
{
   MetodCagir();
}

private static void MetodCagir()
{
   NeredenGeldim("Bir metodun serancamı:");
}

public static void NeredenGeldim(string parametre, [CallerMemberName]string cagiranMetodAdi = "", [CallerFilePath]string cagiranDosyaYolu = "", [CallerLineNumber]int cagiranSatirNumarasi = 0)
{
   Console.WriteLine(parametre);
   Console.WriteLine("Çağıran Metodun Adı : " + cagiranMetodAdi);
   Console.WriteLine("Çağıran Metodun Dosya Yolu : " + cagiranDosyaYolu);
   Console.WriteLine("Çağıran Metodun Satır Numarası : " + cagiranSatirNumarasi);
   
   Console.Read();
}

Çıktı:

Buraya kadar her şey güzel. Ama .NET Framework’ün eski versiyonlarında bu “attribute”leri kullanamıyoruz. Bunun için yapabileceğimiz şey tüm versiyonlarda bulunan aslında fazlasıyla aşina olduğumuz bir sınıfı kullanacağız: StackTrace!

İlk etapta eski versiyonlar için metodu oluşturalım:

public static void NeredenGeldimEskiVersiyonlar(string parametre, string cagiranMetodAdi = "", string cagiranDosyaYolu = "", int cagiranSatirNumarasi = 0)
{
   StackTrace st = new StackTrace(true);
   StackFrame[] frames = st.GetFrames();

   Console.WriteLine(parametre);
   Console.WriteLine("Çağıran Metodun Adı : " + cagiranMetodAdi);
   Console.WriteLine("Çağıran Metodun Dosya Yolu : " + cagiranDosyaYolu);
   Console.WriteLine("Çağıran Metodun Satır Numarası : " + cagiranSatirNumarasi);
 
   Console.Read();
}

Burada StackTrace’in her bir “frame“i aslında hata mesajlarında gördüğümüz satırları ifade ediyor ve aşağıdaki gibi gözüküyor:

İncelediğimizde içinde bulunduğuz metoddan başlayarak hiyerarşik bir şekilde metodların “frame” dizisinde listelendiğini görüyoruz.

Gördüğünüz gibi olay “Caller Info Attributes”teki kadar kolay değil. Geldiğimiz metodu tespit etmek için bir şekilde dizinin elemanlarını bir şekilde filtrelememiz lazım.

Bunun için de “frame”lerin içeriğine biraz daha yakından bakalım. Örneğin bizim aradığımız metod olan “MetodCagir“ı içeren “frame”i inceleyelim:

Burada “Frame“in altında “DeclaringType“ı ve onun “property“leri arasında ise “Name” ve “FullName” alanlarını görüyoruz. “FullName”den yararlanarak metodumuzu çağıran programı filtreleyebiliriz. Örneğimizde hepsi “MerhabaDunya.Program” olsa da kurumsal programlarda pek çok farklı proje entegre bir şekilde çalıştığı için farklı isimler bulunabilir bu kısımda.

Bu yüzden ilk etapta bir LINQ sorgusuyla “FullName”e göre filtreleyip neler olduğuna bakıyorum.

“frames” değişkenin atamasını güncelleyelim:

StackFrame[] frames =
 st.GetFrames()
 .Where(s => s.GetMethod().DeclaringType.FullName.Contains("MerhabaDunya.Program"))
 .ToArray();

Örneğe göz atmadan önce bir NOT: Bu arada ben LINQ sorgusu kullanacağım için .NET Framework 3.5 da çalıştırıyorum programı. LINQ sorgusuna ihtiyacınız yoksa daha alt versiyonlarda da bu yöntemi kullanabiliyorsunuz.

Şimdi debug modda “frames”e bakalım tekrar:

Görüldüğü üzere 3 metod kaldı. (Bu da demek oluyor ki dışarıda kalan 4 metod programımıza değil .NET Framework’e ait metodlardı.)

Bu metodlar da sırasıyla:

  • NeredenGeldimEskiVersiyonlar(İçinde bulunduğumuz metod)
  • MetodCagir(Metodumuza çağıran, asıl aradığımız metod)
  • ve Main metodu.

Artık filtreleme yaptığım sorguya bir şart daha ekleyerek aradığım “frame”e ulaşabilirim:

“Metod ismi ‘NeredenGeldimEskiVersiyonlar’ olmayan ilk ‘frame’i getir ve bilgilerini yazdır.”

Yazıyı daha fazla uzatmadan kodun son haline bakalım:

public static void NeredenGeldimEskiVersiyonlar(string parametre, string cagiranMetodAdi = "", string cagiranDosyaYolu = "", int cagiranSatirNumarasi = 0)
{
   StackTrace st = new StackTrace(true);
   StackFrame[] frames = st.GetFrames();
   StackFrame frame = new StackFrame();

   if (frames != null)
   {
      frame = frames.FirstOrDefault(s => s.GetMethod().DeclaringType.FullName.Contains("MerhabaDunya.Program") && s.GetMethod().Name != "NeredenGeldimEskiVersiyonlar");
      cagiranMetodAdi = frame.GetMethod().Name;
      cagiranDosyaYolu = frame.GetFileName();
      cagiranSatirNumarasi = frame.GetFileLineNumber();
   }
 
   Console.WriteLine(parametre);
   Console.WriteLine("Çağıran Metodun Adı : " + cagiranMetodAdi);
   Console.WriteLine("Çağıran Metodun Dosya Yolu : " + cagiranDosyaYolu);
   Console.WriteLine("Çağıran Metodun Satır Numarası : " + cagiranSatirNumarasi);

   Console.Read();
}

Ve çıktı:

Gördüğünüz üzere aslında C# 5’te hayatımıza giren bir çözüme eski versiyonlarda ulaşmak için bir “workaround” çözüm geliştirdim. Tahmin edeceğiniz üzere bu gerçek hayatta karşılaştığım bir problemi aşmak için bulduğum çözüm. Bundan daha temiz bir çözüm de olabilir elbette. Benden şimdilik bu kadar.

Kendinize çook iyi davranın.

 Bu sayfa 507 kez görüntülendi

It's only fair to share...Share on LinkedInShare on FacebookShare on Google+Tweet about this on TwitterShare on Tumblr
Benzer Konular

Yorum Yap


Not - Bunları KullanabilirsinizHTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>