In operatörü

Nisan 28, 2012 at 10:16 mehmet.baran

Merhaba,

SQL'de çok sık kullandığımız bir ifade vardır. Where kısmında bir değerin bir kümede bulunup bulunmama koşulunu In anahtar kelimesini kullanarak yazarız. Bunun için bir sürü OR yazmaktansa IN ifadesi ile çok temiz bir syntax oluşturmuş oluruz:

 SELECT * FROM TABLE_A A WHERE A.COLUMN_B IN (1,2,3,4,5)

Peki C#'ta da buna benzer bir koşul ifadesi yazabilir miyiz? Aslında böyle bir özellik yok fakat Extension Methodlarla bu işlemi yapabiliriz. Aşağıda Object sınıfına, yani tüm sınıflara IN metodunu ekliyoruz:

public static bool In(this object t, params object[] values)
{
    foreach (object value in values)
    {
         if (t.Equals(value))
         {
              return true;
         }
    }
    return false;
}

Yazdığım metoda baktığımız zaman parametre olarak N tane object almakta ve asıl nesneyi verilen kümede aramaktadır. Kullanımı ise şu şekilde olacaktır:

if ("9".In("1""2""3""4"))
{
     // ...
}

http://www.extensionmethod.net/ adresine girerek birçok kullanışlı extension metodlar bulabilirsiniz.

Posted in: .Net

Tags:

Operator Overriding

Nisan 27, 2012 at 5:07 mehmet.baran

Merhaba,

Hepimiz tiplerimiz arasında bazı ilişkileri tanımlamak için yeni metodlar geliştiririz. Peki bu ilişkileri toplama, çıkarma vb. operatörler ile tanımlamak daha kolay olmaz mıydı? Aşağıdaki ComplexNumber sınıfını ve test kodunu inceleyelim:

class Program
{
    static void Main(string[] args)
    {
        ComplexNumber c1 = new ComplexNumber(2, 1);
        ComplexNumber c2 = new ComplexNumber(3, 1);
 
        ComplexNumber c3 = c1 + c2;
 
        Console.WriteLine("{0}+{1}i", c3.Real, c3.Imaginary);
        Console.ReadLine();
    }
}
 
class ComplexNumber
{
    public int Real { getset; }
    public int Imaginary { getset; }
 
    public ComplexNumber(int real, int imaginary)
    {
        this.Real = real;
        this.Imaginary = imaginary;
    }
 
    public static ComplexNumber operator +(ComplexNumber a, ComplexNumber b)
    {
        return new ComplexNumber(a.Real + b.Real, a.Imaginary + b.Imaginary);
    }
}

ComplexNumber sınıfında "ComplexNumber + ComplexNumber" işleminin tanımı operator overriding yöntemi ile yazılmış. Test kodunda da görüleceği üzere sanki iki integer değişken toplanır gibi toplama işlemi yapılabilmiş. Birçok noktada bize kolaylıklar sağlayacağı kesin. 

Posted in: .Net

Tags:

String.Join ve String.Concat

Nisan 25, 2012 at 2:42 mehmet.baran

Merhaba,

Birçok defa stringleri birbirine ekleyip tek bir string oluşturma ihtiyacımız olmuştur. Bunun için birçok alternatif yöntem kullanılabilir. Peki elimizdeki liste çok uzunsa bunu nasıl yapmak lazım? Aşağıdaki kod parçasına ve çıktısına bakalım:

static void Main(string[] args)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    var result1 = String.Join(";"Enumerable.Range(0, 200000).Select(n => n.ToString()));
    sw.Stop();
    Console.WriteLine("result1..:" + sw.ElapsedMilliseconds + "ms");
 
    sw.Reset();
    sw.Start();
    var result2 = Enumerable.Range(0, 200000).Select(n => n.ToString()).Aggregate((a, b) => String.Concat(a, ";", b));
    sw.Stop();
    Console.WriteLine("result2..:" + sw.ElapsedMilliseconds + "ms");
 
    Console.ReadLine();
}

Görüldüğü gibi 200000 tane stringi ard arda ";" ile eklemek için String.Join metodu çok daha hızlı. 

Posted in: .Net

Tags:

Cast Overriding

Nisan 19, 2012 at 9:28 mehmet.baran

Merhaba,

Bazı durumlarda kendi oluşturduğumuz tiplere casting işlemi yapmamız gerekebiliyor. Bunlar için property veya metodlar yazabiliriz. Aşağıdaki örneği incelersek, anlatmak istediğimi çok daha açık anlayabiliriz. 

    class MyInt32
    {
        private Int32 _IntValue;
 
        public Int32 IntValue 
        {
            get { return _IntValue; }
            set { _IntValue = value; }
        }
    }

Yazdığım sınıfta Int32 sınıfının kendime göre özelleştirilmişini oluşturmaya çalıştım. Tabiki içeride Int32 olarak da değeri koruyorum. Peki benim sınıfımın nesnelerine asıl Int32 değerleri nasıl atanacak? Bunun için bir property yazdım ve Int32 casting işlemi bu property ile yapılabilir. Tıpkı aşağıdaki gibi:

    static void Main(string[] args)
    {
        MyInt32 myInt = new MyInt32();
        myInt.IntValue = 5;           
    }

Peki daha doğal bir yöntemi yok mudur bu işlemin? Tabiki C# bize böyle bir imkan sunuyor. Int32'den MyInt32'ye cast işlemini override ederek bu işi çok daha kolay bir şekilde yapabiliriz. Şimdi kendi sınıfıma bu cast overriding işlemi için bir metod daha ekliyorum:

    class MyInt32
    {
        private Int32 _IntValue;
 
        public Int32 IntValue 
        {
            get { return _IntValue; }
            set { _IntValue = value; }
        }
 
        public static implicit operator MyInt32(Int32 i)
        {
            MyInt32 tmp = new MyInt32();
            tmp.IntValue = i;
            return tmp;
        }
    }

Burada implicit operator öneki ile Int32 nesnesinden MyInt32 nesnesinin nasıl elde edileceğini yazmış olduk. Böylece artık kodumuzu aşağıdaki gibi değiştirebiliriz:

    static void Main(string[] args)
    {
        MyInt32 myInt = new MyInt32();
        myInt = 5;                       
    }

Örnekteki kullanımında olay çok basit gelebilir fakat bazı durumlarda kodun okunabilirliğini ciddi şekilde arttırmaktadır. Unutulmaması gereken bir nokta ise her casting işleminde yeni bir nesne oluşmaktadır. Bundan dolayı bu yöntem kullanılmadan önce bellek yönetimi ve performansta göz önünde bulundurulmalıdır. 

Posted in: .Net

Tags:

Global Exception Handler

Mart 23, 2012 at 11:10 mehmet.baran

Merhaba,

C#'da kod yazarken exceptionları çok dert etmeyiz kendimize. Çünkü kodumuz try-catch blogunda olduğu sürece  uygulamanın çalışması konusunda sıkıntı çıkmayacaktır. Fakat C/C++ gibi dillerde exception alan uygulama genellikle ancak yeniden başlatılarak kurtarılır. 

Peki C#'da bir exception'i yakalayamazsak ne olur? Tabiki uygulama kapanır. Peki bu durumda uygulamanın ne zaman, nasıl, neden kapandığını bulamaz mıyız? Bulabilirsek çok işimize yarayacağı kesin. 

İşte tam olarak bu ihtiyaç için bir özellik var C#'da. UnhandledException diye adlandırılan bu yapı şöyle çalışıyor. 

    class Program
    {
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
            int i = 0;
            int a = 5 / i; // Exception fırlayacak satır
            Console.WriteLine("Çalışmayacak kod satırı");             Console.ReadLine();         }         static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)         {             Console.WriteLine("Exception yakalandı");             Console.WriteLine("-->" + ((Exception)e.ExceptionObject).Message);             Console.WriteLine("-->" + ((Exception)e.ExceptionObject).StackTrace);                         Console.ReadLine();         }     }
 

Uygulamanın daha ilk satırında yakalanmayan bir exception olduğunda CurrentDomain_UnhandledException adlı metodun çağrılması için kayıt yapıyorum. Böylece uygulamanın herhangi bir yerinde alınacak exceptionlar için bu metod çağrılacak. Metodun içinde ne yapacağım ise bana kalmış. En mantıklısı temiz bir loglama yapmak. Böylece dönüp baktığımda en azından uygulamanın crash olmasına dair bir sürü ipucum olur. 

Burada dikkat edilmesi gereken noktalardan biri ise uygulamanın normal akışının devamıdır. Yani burda bana sadece uygulama kapanmadan önce son bir loglama şansı veriliyor ve uygulama yine crash oluyor. 

Posted in: .Net

Tags: ,

ILGenerator ile Dynamic Method

Şubat 14, 2012 at 11:32 mehmet.baran

Merhaba,

Ne zamandır inceleyip bir yazı yazmak istiyordum bu konuda. Gelelim konumuza. ILGenerator'la geliştirme yapmaya ne zaman ihtiyacımız olur onun net bir cevabı yok aslında ama birçok kullanım yeri olduğunu biliyorum. Ben örnek olması açısından "Merhaba Dünya" tarzında birşeyler yapacağım. Aşağıdaki kodu inceleyelim:

class Program
{
    public delegate void Write(String str);
    static void Main(string[] args)
    {            
        DynamicMethod methodWrite = new DynamicMethod("Write"nullnew Type[] { typeof(String) });
        ILGenerator il = methodWrite.GetILGenerator();
        il.Emit(OpCodes.Ldstr, "Merhaba ");
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Call, typeof(string).GetMethod("Concat"new Type[]{typeof(String), typeof(String)}));
        il.Emit(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine"new Type[]{typeof(string)}));
        il.Emit(OpCodes.Ret);                                    
 
        Write writer = (Write)methodWrite.CreateDelegate(typeof(Write));
        writer("Mehmet");                      
    }
} 
 

Yazdığım kod bildiğimiz bir console uygulamasına ait bir kod. Öncelikle delegate tanımına dikkat etmek lazım. Burda içi olmayan bir metod tanımı yapıyoruz. C++ 'taki fonksiyon pointer'i gibi düşünebiliriz. Daha sonra main metodunun içinde DynamicMethod oluşturup, ILGenerator ile metodun içini yazıyoruz.

Metodun içini yazarken sırasıyla yaptıklarımız şunlar:

1. Metod için oluşturulan stack alana "Merhaba" değerini ekliyoruz.

2. Stack alana 0.parametrede gelen değeri ekliyoruz.

3. String.Concat metodonu çağırıyoruz. Bu metod stack alandaki en son 2 değeri alıp string olarak birleştirdikten sonra çıkan sonucu da stack alana ekler. Bu işlemden sonra stackteki ilk iki değer silinmiş sadece yeni değer eklenmiş olur. 

4. System.Concole.WriteLine(String) metodunu çağırıyoruz. Bu metod stack alandaki en son değeri ekrana yazdırır.

5. Son olarak metoda return ekliyoruz.

Böylece metodumuz oluşmuş oluyor. Sonra oluşturdumuz bu dinamik metodu Write delegasyon metoduna atıyoruz. Böylece metodumuz çalıştırılmaya hazır. Son satırda ise metodu çağırıyoruz.

Burada gözden kaçmaması gereken durum kodun tamamen runtime'da yazılıp derlenip çalıştırılıyor olmasıdır. Kompleks kodlar yazmak gerektiğinde ve özellikle performans beklenen yerlerde ILGenerator ile çok başarılı işler yapılabilir.

Aşağıda da yine iki sayıyı toplayan bir metodun dinamik olarak yazımı var:

class Program
{
    public delegate int Sum(int a, int b);
 
    static void Main(string[] args)
    {
        DynamicMethod methodSum = new DynamicMethod("Sum"typeof(int), new Type[] { typeof(int), typeof(int) });
        ILGenerator il = methodSum.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0); // Stack Durumu : 3
        il.Emit(OpCodes.Ldarg_1); // Stack Durumu : 3, 5
        il.Emit(OpCodes.Add);     // Stack Durumu : 8             
        il.Emit(OpCodes.Ret);
 
        Sum summer = (Sum)methodSum.CreateDelegate(typeof(Sum));
        int result = summer(3, 5);                      
    }
}      

 

Posted in: .Net

Tags: , , ,

DesingMode Hatalarına Önlem

Şubat 7, 2012 at 4:28 mehmet.baran

Merhaba,

Visual Studio'da, Windows Form uygulamaları geliştirirken bazen design mode 'da ekranı açarken hatalar alabiliyoruz. Bunun sebebi design mode dahi olsa aslında ekran kodlarınızın visual studio tarafından çalıştırılıyor olması. Örneğin form veya bir controlün constructor kısmında veri tabanına bağlanma, web servis çağrısı, dosya okuma-yazma gibi hata alması muhtemel kod blokları çalışıyor ise ekranı design mode'da açamamanız mümkün. 

Bu tür hataların önüne geçmek için kod bloklarının design time'da çalışmasını engelleyebiliriz.

if(DesignMode) // Component.DesignMode
{
    return;
}

şeklinde bir kod parçası ile design mode hataların önüne geçebiliriz.

Fakat contructorda yazılan kod bloklarında henüz controle ait tüm bileşenler hazır olmadığı için DesignMode property'si her durumda false dönecektir. Bunun için de 

if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) 
{
    return;
}

şeklinde bir kontrol ifadesi kullanabiliriz. 

 

Posted in: .Net | Windows Forms

Tags: , ,

NHibernate - INamingStrategy Implementation

Kasım 21, 2010 at 4:03 mehmet.baran
NHibernate - INamingStrategy Implementation

Merhaba,

Bu yazımda NHibernate'in pek bilinmeyen bir özelliğinden bahsedeceğim. NHibernate de pocolar için insert, update, delete ve select queryleri dinamik olarak üretilmektedir. Bu queryler oluşturulurken "poco_name.hbm.xml" dosyalarındaki table-class mapping bilgilerinden yararlanılır. Burada tablo ismi ve sütun isimleri alınarak bir query oluşturulur. 

Peki bu isimlendirmelere çalışma zamanında nasıl müdahele edebiliriz? Bunu INamingStrategy interface'ini implemente ederek yapabiliriz. Örneğin aşağıdaki sınıfı inceleyelim. 

public class NamingStrategyImpl : INamingStrategy
{
    public string ClassToTableName(string className)
    {
        return DefaultNamingStrategy.Instance.ClassToTableName(className);
    }
    public string PropertyToColumnName(string propertyName)
    {
        return DefaultNamingStrategy.Instance.PropertyToColumnName(propertyName);
    }
    public string TableName(string tableName)
    {
        tableName = tableName.ToUpper();
        return DefaultNamingStrategy.Instance.TableName(tableName);
    }
    public string ColumnName(string columnName)
    {
        columnName = columnName.ToLower();
        return DefaultNamingStrategy.Instance.ColumnName(columnName);
    }
    public string PropertyToTableName(string className, string propertyName)
    {
        return DefaultNamingStrategy.Instance.PropertyToTableName(className, propertyName);
    }
    public string LogicalColumnName(string columnName, string propertyName)
    {
        return DefaultNamingStrategy.Instance.LogicalColumnName(columnName, propertyName);
    }
}

Burda tableName, columnName vs. değerlerinin oluştuğu metodlar bulunmaktadır. Örneğin dinamik oluşturulacak query içinde tablo adı öncelikle poco_name.hbm.xml dosyasından okunur sonra burdaki TableName metoduna parametre geçilerek geri alınan değer kullanılır. Örnekte tablo ismi büyük harflere çevrilmiştir. Benzer şekilde tablo ismi üzerinde ihtiyaca göre çeşitli değişiklikler yapılabilir. Çalışan sistemlerde veritabanı değişikliklerinde bazen bu tür kodlar işimizi oldukça kolaylaştırabilir. 

Peki bu sınıfı yazdıktan sonra NHibernate kütüphanesinin bu implementasyonu kullanmasını nasıl sağlayacağız? Cevabı basit. SessionFactory nesnesi oluştururken. Örnek kod aşağıdadır.

var config = new Configuration();
config.SetNamingStrategy(new NamingStrategyImpl());
_SessionFactory = config.Configure().BuildSessionFactory();

Kolay gelsin

Posted in: .Net | NHibernate

Tags: , ,

Extension Methods

Kasım 19, 2010 at 6:59 mehmet.baran
Extension Methods

Merhaba,

C# 3.0 ile gelen yeni bir özellik olan Extension Method'dan bahsedeceğim. Extension metodlar tiplere sonradan yeni metodlar kazandırmaya yarıyor. Bu kendi tiplerimiz olabileceği gibi herhangi bir system tipi de olabilir. Örneğin string sınıfına aşağıda long tipine dönüşüm sağlayan extension metod yazılmıştır. 

namespace System
{

    
public static class StringExtensions
    {

        
/// <summary>
        
/// String'in degerini long'a convert eden metod.
        
/// </summary>
        
/// <param name="t">Tip</param>
        
/// <returns>long deger</returns>
        
public static long ToLong(this string t)
        {
            
return Convert.ToInt64(t);
        }
    }
}

Bu metod şu şekilde kullanılabilir: 

String str = "30";
long lng = str.ToLong();

Burada dikkat edilmesi gereken metodun static bir metod olması ve ilk parametre olarak extend etmek isteğimiz sınıf tipinde bir parametre almaktır. "this" anahtar sözcüğü tipin extend edileceğini gösterir. Bu şekilde istediğiniz her tipe yeni yeni özellikler kazandırılabilir.

Unutmadan dikkat edilmesi gereken bir nokta, extension metodu kullanmak istediğiniz yerde mutlaka using ifadesi ile extension metodun olduğu namespace'i dahil etmelisiniz. Küçük bir ipucu: örnekte olduğu gibi namespace'i System yaparsanız otomatik olarak heryerde erişim sağlamış olursunuz. 

http://www.extensionmethod.net/ adresindeki hazır yazılmış extension metodları kullanabilirsiniz. Hatta kendi yaptıklarınızı da yayınlayabilirsiniz.

Posted in: .Net

Tags: , ,

Type.GetType(String typeName) Metodu

Kasım 19, 2010 at 6:39 mehmet.baran
Type.GetType(String typeName) Metodu

Merhaba,

Bu entryde Type.GetType metodunun başka bir assemblydeki bir sınıf için nasıl kullanılması gerektiğinden bahsedeceğim. 

C# da reflection kullanan herkesin mutlaka kullandığı bir metoddur Type.GetType(). Kısaca açıklamak gerekirse namespace+className'ini bildiğimiz bir sınıfın tipini elde etmeye yarar. Örnek verecek olursak;

Type t = Type.GetType("Namezpace.ClassName");

ifadesi "ClassName" sınıfının tipini döndürür. Fakat ilgili tip başka bir assembly'de ise null döner. Bu durumu çözmek için aynı string içinde virgül ile ayırarak assembly adı da verilmelidir. Yani;

Type t = Type.GetType("Namezpace.ClassName, AssemblyName");

şeklinde yazılmalıdır. 

Posted in: .Net

Tags: , , ,