Makale Özeti

Bu makalemde inceleyeceğimiz konu exceptionlar ve kendi exception classımızı nasıl yazabileceğimizdir. Öncelikle uygulamalarda kendi exception class'ımızı neden yazmaya gerek duyarız sorusunu cevabını arayalım.

Makale

         Merhabalar,

         Bu makalemde inceleyeceğimiz konu exceptionlar ve kendi exception classımızı nasıl yazabileceğimizdir. Öncelikle uygulamalarda kendi exception class'ımızı neden yazmaya gerek duyarız sorusunu cevabını arayalım. Uygulamamızda oluşabilecek exceptionlara örnek vermeye çalıırsak DataBase tarafından üretilen exceptionlar(örn StoredProcedurede tanımlanmış parametrenin Command Nesnesine atanmamış olması,Select sorgusu yapılan tablonun database de olmaması) kullanıcıya database'imizin yapısı bakımından bilgi vereceği ve kullanıcı için pek birşey ifade etmeyeceğinden mesajları kullanıcıya direkt gösterilmemelidir ve yerine kullanıcının anlayabileceği bir mesaj gösterilmelidir(Örn. DataBase Hatası.). Ancak throw new Exception("Tarih1 Tarih2 den büyük olamaz") şeklinde bir exception fırlattığımızda bu mesajı kullanıcı görmelidir. Yine aynı şekilde 1. örnekteki exceptionlarımızı loglamak veya haberdar olmak için kendimize mail attırmak isterken 2. örnekteki exception için böyle bir isteğimiz olmayabilir. Her bir Catch bloguna bu exception olduğunda mail at veya logla gibi bir kod yazmaktansa kendi exception Classlarımızı yazmamız daha pratik olacaktır. Şimdi istereniz bir Windows uygulaması üzerinde bu dediklerimizi hayata geçirerek olay hakkında bilgi sahibi olalım.

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Configuration;
using System.Net.Mail;

namespace ExceptionManagement
{
      public class MyBaseException : ApplicationException
      {

          Görüldüğü gibi classımızı genel bir Exception class'ı olan ApplicationException'dan inherit ediyoruz. System.Net.Mail namespace'ini kullanarak mail yollayacağımız için using System.Net.Mail satırını kodumuzua ekliyoruz. Yaratmış olduğumuz bu class genel exception property'lerimizi ve metodlarını taşıyacaktır hiçbirzaman uygulamamızda throw MyBaseException gibi bir kod yazmayacağız.

            #region "Properties"
                  private string mPublicExceptionMessage;
                  public string PublicExceptionMessage
                  {
                        get { return mPublicExceptionMessage; }
                        set { mPublicExceptionMessage = value; }
                  }
            #endregion

          Bu regionda Exception class'ımızda bulunacak PublicExceptionMessage isimli property'i tanımlıyoruz. String tipindeki bu property bizim işimize kullanıcıya Exception mesajından farklı bir mesaj göstermek istediğimizde işimize yarayacaktır.

            #region "Ctors"
                  public MyBaseException():base()
                  {
                  }
                  public MyBaseException(string message)
                        : base(message)
                  {                
                  }
                  public MyBaseException(string message, Exception innerException)
                        : base(message, innerException)
                  {
                  }
                  public MyBaseException(string message, string publicMessage) : base(message)
                  {
                        mPublicExceptionMessage = publicMessage;
                  }
            #endregion

          Bu kısımda inherit ettiğimiz class olan ApplicationException class'ımızdaki tüm Constructorlara(Yapıcı Metodlara) karşılık gelen ve baseinde bulunan yapıcı metodu çağıracak şekilde bir Constructor yazıyoruz. Ancak en son yazdığımız Constructorda dışarıdan biraz önce bahsettiğimiz kullancıya gösterlecek mesajı barındıran bir parametre kullanıyoruz.

            #region "Methods"
                  public void funSendMail()
                  {
                        MailMessage mm = new MailMessage(ConfigurationManager.AppSettings["ExceptionMailTo"].ToString(),ConfigurationManager.AppSettings["ExceptionMailFrom"].ToString());
                        mm.Subject = ConfigurationManager.AppSettings["ExceptionMailSubject"].ToString();
                        mm.IsBodyHtml = true;
                        mm.Body = ConfigurationManager.AppSettings["MailBody"].ToString().Replace("%hataMesaji%", this.Message);
                        SmtpClient smtp = new SmtpClient(ConfigurationManager.AppSettings["MailServer"].ToString());
                        smtp.Send(mm);
                  }

          Şimdi ise sırada Exception oluştuğunda mail yollyacak lan metodumuzu yazmaya geldi. Önemli bir nokta bu mesaj oluşturlurken kullanılan birçok değişkenin Application'un Config dosyasından okunmasıdır. Kodun bu şekilde yazılmasının sebebi bu değişiklikleri yaptığımızda uygulamamızı bir daha compile etme gereksiniminin ortadan tamamiyle kaldırılmasına yöneliktir. Bu Config dosyasının yapısını bu class'ımızı yazmayı bitirdiğimizde inceleyeceğiz. Bu metodda ilk önce from ve to parametrelerini vererek bir mail mesajı tanımlıyoruz. daha Sonrasında ise bu mailin Subject'ini, HTML bir Body'e sahip olup olmadığını, ve Bodysinde hangi mesajın bulunduğunu tanımladıktan sonra sıra Maili yollamak için kullanacağımız bir SmtpClient tanımlamaya geliyor. SmtpClient'imizide Sunucu adresini belirleyerek tanımlıyoruz ve Send metoduna mail mesajımızı parametre olarak vererek mailimizin yollanmasını sağlıyoruz.

                  public void funWriteEventLog()
                  {
                        if(!EventLog.Exists(ConfigurationManager.AppSettings["MyExceptionEventLogName"].ToString()))
                        {
                              EventSourceCreationData escd = new EventSourceCreationData(ConfigurationManager.AppSettings["MyExceptionEventLogName"].ToString(), ConfigurationManager.AppSettings["MyExceptionEventLogName"].ToString());
                              escd.MachineName=Environment.MachineName;
                              EventLog.CreateEventSource(escd);
                        }
                        EventLog.WriteEntry(ConfigurationManager.AppSettings["MyExceptionEventLogName"].ToString(), this.Message);
                  }
            #endregion           
      }
}

          Şimdi ise Exceptionumuz oluştuğunda bu mesajı EventLog'a yazacak olan metodumuzu  yazıyoruz. Bu metodda bütün parametrik verilerini Application Config dosyasından almaktadır. İlk önce belirlediğimiz isimde bir EventLog yaratılıp yaratılmadığını kontrol ediyor ve yaratılmamış ise bu event log u yaratıyoruz. Daha Sonrasında ise EventLog Classının WriteEntry Static metodunu kullanarak Exception mesajımızı EventLog'a yazmayı bitirmiş oluyoruz.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
      <
appSettings>
            <
add key="MyExceptionEventLogName" value="MyException"></add>           
            <
add key="ExceptionMailTo" value="oztamer@hotmail.com"></add>
            <add key="ExceptionMailFrom" value="hata@hata.com"></add>
            <add key="ExceptionMailSubject" value="Hata Olustu"></add>
            <add key="MailServer" value="localhost"></add>
            <add key="MailBody" value="Sistemde Bir Hata Olustu. hata Mesaji : %hataMesaji%"></add>
      </
appSettings>
</
configuration>

          App.Config dosyamızda ise metodlarımızda kullanacağımız parametrik değişkenlerimizi tanımlıyoruz. Bu parametrelerden biri değiştiği zaman bu dosyayı açıp ilgili parametreyi değiştirmemiz yeterli olacaktır.

         Şimdi ise diğer exception class'larımızı yazdığımız base Exception class'ımızdan türetmeye başlayalım.

      public class JustDisplayException : MyBaseException
      {
            public JustDisplayException()
                  : base()
            {
            }
            public JustDisplayException(string message)
                  : base(message)
            {
            }
            public JustDisplayException(string message, string publicMessage)
                  : base(message,publicMessage)
            {
                  throw new MyBaseException(publicMessage, this);
            }
      }

          Oluşturduğumuz bu Exception class'ımızın yapıcı metodlarında görüldüğü gibi fırlatılan Exception ile herhangi bir işlem yapılmamaktadır, Ancak En son metodumuzda görüleceği gibi eğer bir PublicExceptionMessage parametresi yollanmışsa oluşan exceptionun içinden yeni bir exception fırlatıyoruz ve fırlattığımız bu yeni exceptionun innerException özelliğine exceptionumuzu, Message özelliğine ise kullanıcıya gösterilmesini istediğimiz mesajı barındıran parametre olan publicMessage değişkenimizi veriyoruz.

      public class MailSenderException : MyBaseException
      {
            public MailSenderException()
                  : base()
            {
                  this.funSendMail();    
            }
            public MailSenderException(string message)
                  : base(message)
            {
                  this.funSendMail();
            }
            public MailSenderException(string message, string publicMessage)
                  : base(message,publicMessage)
            {
                  this.funSendMail();
                  throw new MyBaseException(publicMessage, this);
            }
      }

          Bu exception class'ımızda ise bir öncekinden farklı olarak Exceptionumuz fırladığında yapıcı metodlarda BaseException class'ımıza yazmış olduğumuz ve mail yollama görevini üstlenmiş funSendMail() isimli metodumuzu çağırıyoruz.
 

      public class EventWriterException : MyBaseException
      {
            public EventWriterException()
                  : base()
            {
                  this.funWriteEventLog();     
            }
            public EventWriterException(string message)
                  : base(message)
            {
                  this.funWriteEventLog();
            }
            public EventWriterException(string message,string publicMessage)
                  : base(message,publicMessage)
            {
                  this.funWriteEventLog();
                  throw new MyBaseException(publicMessage, this);
            }
      }

          EventWrıterException exception class'ımızda ise MailSenderException exception classımızdaki ile aynı bir yapıda her exception fırladığında Base Classımıza yazmış olduğumuz. funWriteEventLog metodunu çağırıyoruz.
 

      public class EventWriterAndMailSenderException : MyBaseException
      {
            public EventWriterAndMailSenderException()
                  : base()
            {
                  this.funWriteEventLog();
                  this.funSendMail();
            }
            public EventWriterAndMailSenderException(string message)
                  : base(message)
            {
                  this.funWriteEventLog();
                  this.funSendMail();
            }
            public EventWriterAndMailSenderException(string message, string publicMessage)
                  : base(message,publicMessage)
            {
                  this.funWriteEventLog();
                  this.funSendMail();
                  throw new MyBaseException(publicMessage, this);
            }
      }

          Bir önceki Exception classlarımızla yapısal olarak aynı olan bu exception classımız ise hem EventLog'a girdi yazmakta hemde mail yollamaktadır.

         Şimdi ise yazmış olduğumuz bu exceptionları bir Windows uygulamasında test edelim.

            private void Form1_Load(object sender, EventArgs e)
            {
                  try { throw new JustDisplayException("Sadece Gostermelik");}
                  catch (Exception ex){MessageBox.Show(ex.Message);}
 
                  try { throw new JustDisplayException("Sadece Gostermelik","Kullanici Mesaji"); }
                  catch (Exception ex) { MessageBox.Show(ex.Message); }
 
                  try { throw new MailSenderException("Mail Yollandi"); }
                  catch (Exception ex) { MessageBox.Show(ex.Message); }
 
                  try { throw new JustDisplayException("Mail Yollandi","Kullanici Mesaji"); }
                  catch (Exception ex) { MessageBox.Show(ex.Message); }
 
                  try { throw new EventWriterException("EventLog Yazildi"); }
                  catch (Exception ex) { MessageBox.Show(ex.Message); }
 
                  try { throw new EventWriterException("EventLogYazildi","Kullanici Mesaji"); }
                  catch (Exception ex) { MessageBox.Show(ex.Message); }
 
                  try { throw new EventWriterAndMailSenderException("EventLog Yazildi ve Mail Yollandi"); }
                  catch (Exception ex) { MessageBox.Show(ex.Message); }
 
                  try { throw new EventWriterAndMailSenderException("EventLog Yazildi ve Mail Yollandi","Kullanici Mesaji"); }
                  catch (Exception ex) { MessageBox.Show(ex.Message); }
            }

          Form açıldığı zaman yazdığımız her exceptionun her türünden bir exception yaratıp Genel Exception classı  olan Exception ile yakalıyoruz. Daha sonrasında EventLog'u ve Mailimizi kontrol ederek oluştuduğumuz exception mesajlarının kaydedilip kaydedilmediğini inceliyoruz ve başarıyla çalıştığını görüyoruz.

         Sizde buna benzer bir BaseException class'ı yazarak ve kendi Exceptionlarınızı bu BaseClassdan türeterek Exceptionlarınızı handle edebilirsiniz. Örneğin DataBaseException isminde bir exception yazdınız ve kullanıcıya database hata mesajının gösterilmesini istemiyorsunuz, EventLoga yazılması sizin için bişe ifade etmiyor ancak mutlaka mail atılması lazım gibi bir senaryoda emin olun bu yapı işinizi çok kolaylaştıracaktır. Bunun dışında bir Exception oluştuğunda cep telefonunuza sms atılması, Net send ile mesaj atılması, Msn üzerinden mesaj atılması gibi biraz daha uç noktadaki işleride kendiniz BaseException classınıza bir metod ekleyerek ve bu metodları ilgili exceptionda çağırarak implement edebilirsiniz.

oztamer@hotmail.com
tamer.oz@yazgelistir.com
oztamer@hotmail.com
Örnek Kodlar