Makale Özeti

 Bu makalemizde hem web uygulamalarında hem de windows uygulamalarında ortak kullanabileceğimiz bir session manager yazacağız.

Makale

         Merhaba,

         Bu makalemizde hem web uygulamalarında hem de windows uygulamalarında ortak kullanabileceğimiz bir session manager yazacağız. İsterseniz öncelikle oluşturacağımız yapıyı inceleyelim.



         Artık kodumuzu yazmaya başlayabiliriz. Öncelikle session manager için kullanacağımız interface'lerimizi oluşturalım.

    public interface ISession<T>
    {
        T GetValue(string session);
        void SetValue(string session, T value);
        void Clear(string session);
        void Flush();
    }
    public interface ISessionKeyEnum<T>
    {
        T GetValue(Enum session);
        void SetValue(Enum session, T value);
        void Clear(Enum session);
    }
 
ISession interface'imizde kodumuzdan session üzerinde işlem yapmamıza yarayacak olan metodları oluşturuyoruz. Burada;

GetValue : Verdiğimiz key'e karşılık gelen T generic tipindeki session nesnesini döndüren metoddur.
SetValue : Verdiğimiz key'e T generic tipindeki value nesnesini atayan metoddur.
Clear : Verdiğimiz key'in değerini sıfırlayan metoddur.
Flush : Session'da bulunan tüm değerleri sıfırlayan metoddur.

ISessionKeyEnum interface'imiz kodumuzda session nesnelerine ulaşmak için gerekli key'lerin string olarak hatalı yazmamızı engellemek üzere ISesion'da bulunan tüm metodların bir örneğinin bir enum ile çalışması için tasarlanmıştır. Bu interface'i implement eden Session nesneleri enum ile çalışabilecektir. 

Şimdi session nesnemizi oluşturalım.
    public abstract class Session<T> : ISession<T>, ISessionKeyEnum<T>
    {
        #region ISession<T> Members
        public abstract T GetValue(string session);
        public abstract void SetValue(string session, T value);
        public abstract void Clear(string session);
        public abstract void Flush();
        #endregion
 
        #region ISessionKeyEnumable<T> Members
        public T GetValue(Enum session)
        {
            return GetValue(session.ToString());
        }
        public void SetValue(Enum session, T value)
        {
            SetValue(session.ToString(), value);
        }
        public void Clear(Enum session)
        {
            Clear(session.ToString());
        }
        #endregion
    }
 
Öncelikle bir abstract session nesnesi oluşturuyoruz. Abstract class oluşturma sebebimiz ISessionKeyEnum interface'inde bulunan metodların her session sınıfı için ortak işlem yapacak olmasıdır. Dolayısıyla bu interface'de bulunan metodları oluşturduğumuz her session nesnesi için tekrar tekrar yazmak zorunda kalmayacağız. ISession interface'inde bulunan metodlar her session nesnesi için farklı şekilde çalışacağından bu metodları da abstract olarak tanımlıyoruz.

Şimdi Session nesnelerimizi bu abstract class'dan inherit ederek oluşturalım.
    internal class WebSession<T> : Session<T>
    {
        #region ISessionManager<T> Members
        public override T GetValue(string session)
        {
            object o = System.Web.HttpContext.Current.Session[session];
            if (o == null)
            {
                return default(T);
            }
            return (T)o;
        }
        public override void SetValue(string session, T value)
        {
            System.Web.HttpContext.Current.Session[session] = value;
        }
        public override void Clear(string session)
        {
            System.Web.HttpContext.Current.Session[session] = null;
        }
        public override void Flush()
        {
            System.Web.HttpContext.Current.Session.Abandon();
        }
        #endregion
    }
    internal class WindowsSession<T> : Session<T>
    {
        #region ISession<T> Members
        public override T GetValue(string session)
        {
            return (T)AppDomain.CurrentDomain.GetData(session);
        }
        public override void SetValue(string session, T value)
        {
            AppDomain.CurrentDomain.SetData(session, value);
        }
        public override void Clear(string session)
        {
            AppDomain.CurrentDomain.SetData(session, null);
        }
        public override void Flush()
        {
            throw new NotImplementedException();
        }
        #endregion
    }
 
Gördüğünüz gibi iki tane session nesnesi oluşturduk. Bunlardan biri WindowsSession diğeri ise WebSession isminde ve her ikisi de abstract Session nesnesini iherit ediyor. Her iki nesnenin de içerisinde farklı şekilde yazılmış kodları görüyoruz. WebSession nesnesi tüm işlemleri System.Web.HttpContext.Current.Session nesnesi üzerinden yaparken WindowsSession nesnesi AppDomain.CurrentDomain'i kullanıyor. Bu nesnelerin internal olamalarının sebepleri kendi assembly'leri dışında kullanılmasını istemediğimizden. Yani bu assembly'mizi dll olarak verdiğimiz kullanıcılar hiçbir zaman bu nesneleri inherit edemeyecek ve yeni instance alamayacak.

Şimdi isterseniz SessionManager classımızı yazalım.
    public static class SessionManager<T>
    {
        private static bool IsWebApplication()
        {
            return (System.Web.HttpContext.Current != null);
        }
        public static Session<T> Session
        {
            get
            {
                if (IsWebApplication())
                {
                    return new WebSession<T>();
                }
                else
                {
                    return new WindowsSession<T>();
                }
            }
        }
    }
 
SessionManager nesnemiz esasında çok basit bir çalışma prensibine mevcut. Statik bir nesne ve kullanıcı Session property'sine eriştiği zaman kullanıcının HttpContext'i olup olmadığına bakılarak bir WebSession nesnesi veya bir WindowsSession nesnesi kullanıcıya döndürülüyor. Bu iki nesne Session abstract class'ından inherit olduğundan property'nin dönüş tipi Session<T> olabiliyor ve kullanıcılar bu abstract sınıf içerisinde bulunan metodları çağırabiliyorlar ancak geri döndürdüğümüz nesne tipine göre çalışma mantığı farklı oluyor.

Şimdi isterseniz bir örnek yapalım. Aşağıdaki kodları hem windows hem web uygulamanızda hiçbir değişiklik yapmadan kullanabilirsiniz.
        public enum SessionKeys
        {
            UserName,
            DateOfBirth,
            Company,
        }
        public class Company
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
        static void Main(string[] args)
        {
            //session'a bir deger atiyoruz. Atayacagimiz degerin string tipinden oldugunu generic tipte belirtiyoruz ve SetValue metodunu kullanarak deger atiyoruz.
            SessionManager<string>.Session.SetValue(SessionKeys.UserName, "Yazgeliştir");
 
            //degeri session'dan okumak icin GetValue metodunu kullaniyoruz.
            string s = SessionManager<string>.Session.GetValue(SessionKeys.UserName);
 
            //Ayni sekilde nesneleri de session'a atamak ve sessiondan okumak mumkun
            Company c = new Company { Id = 1, Name = "Yazgeliştir A.Ş." };
            SessionManager<Company>.Session.SetValue(SessionKeys.Company, c);
            Company c1 = SessionManager<Company>.Session.GetValue(SessionKeys.Company);
 
            Console.Read();
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            //session'a bir deger atiyoruz. Atayacagimiz degerin string tipinden oldugunu generic tipte belirtiyoruz ve SetValue metodunu kullanarak deger atiyoruz.
            SessionManager<string>.Session.SetValue(SessionKeys.UserName, "Yazgeliştir");
 
            //degeri session'dan okumak icin GetValue metodunu kullaniyoruz.
            string s = SessionManager<string>.Session.GetValue(SessionKeys.UserName);
 
            //Ayni sekilde nesneleri de session'a atamak ve sessiondan okumak mumkun
            Company c = new Company { Id = 1, Name = "Yazgeliştir A.Ş." };
            SessionManager<Company>.Session.SetValue(SessionKeys.Company, c);
            Company c1 = SessionManager<Company>.Session.GetValue(SessionKeys.Company);
        }
 
Gördüğünüz gibi kodumuzu hiçbir değişiklik yapmadan hem web hem de windows uygulamalarında kullanabiliyoruz. Ayrıca ISession ve ISessionEnumKey veya Session nesnelerini kullanarak kendi session erişim yöntemlerimizi yazabiliriz. Örneğin session'un herhangi bir veri kaynağında saklanmasını kolaylıkla implement edebiliriz.

Umarım faydalı olmuştur.
Tamer ÖZ
oztamer@hotmail.com  
Ornek Kodlar