Oluşturduğumuz assemblyleri Global Assembly Cache'e (GAC) yüklemek için gerek gacutil konsol uygulamasını gerekse de Control Panel\Administrative Tools altındaki Microsoft .NET Framework 2.0 Configuration aracını kullanarak manuel yükleme işlemini gerçekleştirebiliyoruz.

Peki bu işlemi yardımcı araçlar ile manuel olarak değil de bazı ihtiyaçlardan dolayı :) programatik olarak gerçekleştirmek isteyebilirsiniz. Reflector ile biraz .NET'i kurcaladığımda - eh! .net framework kendi içinde böyle bir desteği mutlaka sağlıyordur mantığından yola çıkarak - aşağıdaki resimden de görebileceğiniz GacUtil isimli bir sınıf ile karşılaştım.



Aşağıdaki basit bir reflection işlemi ile kendi assembly'imizi GAC'a yükleyebiliriz.

   1:  namespace BTAkademi.TestCodes
   2:  {
   3:      class Program
   4:      {
   5:          static void Main(string[] args)
   6:          {
   7:              //GAC'dan System.Web dll'i yükleniyor
   8:              Assembly asm = Assembly.Load(@"System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
   9:   
  10:              // Type bilgisi alınıyor
  11:              Type t = asm.GetType("System.Web.Configuration.GacUtil");
  12:              // Metodu invoke edebilmek için GacUtil türünden nesne oluşturuluyor
  13:              object o = Activator.CreateInstance(t);
  14:   
  15:              //Metod bilgisi alınıyor
  16:              MethodInfo mi = o.GetType().GetMethod("GacInstall");
  17:   
  18:              //metod çağrılıyor
  19:              mi.Invoke(o, new object[] { "C:\\gacTest.dll" });
  20:   
  21:          }
  22:      }
  23:  }


Not : GAC'a yüklenmek istenen assembly'nin public key token'a sahip olması gerekmektedir.

 

13/7/2008 tarihli düzenleme :

try
{
    System.EnterpriseServices.Internal.Publish gac = new System.EnterpriseServices.Internal.Publish();
    gac.GacInstall(yuklenecekassemblyadi);
}
catch (System.Security.SecurityException se)
{

}

şeklinde de yüklenebiliniyormuş :))) Eh azmetmek gibisi yok.


 
Categories: .NET | C# | Code | Inceleme

.net dünyasına ilk adım atanlardan sıkça duyduğum soruların başında "bu namespace'leri nerden bileceğim, bu class'ın var olduğunu nerden bileceğim, ya da hangi namespace içerisinde olduğunu nerden bileceğim" şeklinde sorular geliyor. Ben de "zamanla ve kullandıkça, ihtiyacınız oldukça" diye cevaplıyorum.

Şu ve şurdaki linklere dikkat edersek aslında .net framework'ün ne kadar geniş bir dünya olduğunu, hatta biraz abartırsak da "dibsiz bir kuyu" olduğunu da söyleyebilirim ;)

Gün geçmiyor ki yeni assembly'ler, yeni namespaceler ve type'larla karşılaşmayalım sayın programcılar :)


 
Categories: .NET | C# | Inceleme

February 9, 2008
@ 11:59 PM

Linq To SQL de, bir nesne ( Personel ) yüklendiğinde ( from c in DB.Personels select c ) ilişkili olduğu ( Telefon ) tablodaki veriler ( Personele ait Telefonlar )
belleğe yüklenmezler. Aşağıdaki resime bakacak olursak ;




kisi nesnesine ait Ad özelliğinin değeri okunmak istendiğinde zaten bellekte olduğu için yeniden bir işlem yapılmamakta. Ama bu kisi nesnesine ait telefonlar - tablolar arasında ilişki olduğunu biliyoruz - Telefons isimli bir koleksiyon türünden özellik  ile ifade ediliyor. Bu kişiye ait telefon bilgilerinden ilkine erişmek istediğimizde kisi nesnesine ait telefon bilgilerini alıp nesneyle ilişkilendirmek için ikinci bir T-SQL sorgusu veritabanı sunucusuna gönderiliyor. Aslında performans açısından bakıldığında istenen durum budur.

Peki ama ben kisi nesnesini oluşturduğumda buna ait telefon bilgileri de - dikkat edin o kişiye ait adres bilgileri de olabilir ama biz sadece telefon bilgilerinin de - tamamen belleğe yüklensin ikinci bir select işlemi yapılmasın istersek. Bu durumda kodumuza  aşağıdaki gibi eklemeler yapmamız  gerekecektir.



Görüldüğü gibi DataLoadOptions sınıfı ile  nesnenin ilişkili olduğu verilerin de nesne ile birlikte belleğe yüklenmesini sağlayabiliyoruz.  LoadWith Generic metoduna tip olarak Kisi sınıfını verip, lambda Expression ile de Kisi türünden bir nesne yüklendiğinde buna ait telefon bilgilerinin de yüklenmesini ( c => c.Telefons ) belirtebiliyoruz (Immediately Load). DataContext nesnemizin de LoadOptions özelliğine değeri atayarak şekilde görüldüğü gibi iki ayrı select sorgusu ile istediğimiz senaryoyu gerçeklemiş olduk.

 
Categories: C# | Code | Inceleme

C# 3.0 ile birlikte gelen yeniliklerden, otomatik özellikler ile artık kolay ve hızlı bir biçimde standart özellikler (property) tanımlayabiliyoruz.

Örneğin;

class Person
{
   public int No { get; set; }
   public string Ad { get; set; }
   public FizikselOzellik Ozellik { get; set; }
}

class FizikselOzellik
{
   public int Kilo { get; set; }
   public int Boy { get; set; }
   public string Cinsiyet { get; set; }
}

gibi. Aslında IL kodlarını incelersek, derleyicinin C# 2.0 daki gibi (arka planda bir field oluşturup, get ve set erişimcilerini otomatik kendisi yazıyor) özellik tanımladığını görebiliriz. Yeni gelen diğer bir özellik ise Nesneye Ilk Değerini verme ile ilgili. Aşağıdaki sentaks ile artık nesneleri oluştururken özelliklerine de ilk değerlerini vererek nesneyi oluşturabiliriz.


Person nesnemiz içerisinde özellik olarak FizikselOzellik isimli başka bir nesne içeriyor. Bu durumda da aşağıdaki sentaks ile Person nesnemize ilk değerini verebiliriz.,

Person p = new Person {
               
Ad="oguz",No=169,
               Ozellik = new FizikselOzellik{Kilo=120,Boy=173,Cinsiyet="E"}
};

Görüldüğü gibi C# 3.0 ile gelen yenilikleri dili kullanmayı daha hızlı, zevkli ve kolay bir hale getiriyor ;)

 
Categories: C# | Code

February 8, 2008
@ 03:07 PM
İki tabloyu birlikte sorgulamak için inner join kullanırız. Bunu Linq To Sql ile yaparken aşağıdaki gibi bir Linq Query yazarak çözüyoruz
(Kisi, Telefon ve Adres tablolarımız olduğunu, bir kişinin de birden çok adresi ve telefonu olduğunu düşünüyoruz )
Bu sorgu sonucunda bana kişiler tablosundaki isimler ve bunlara ait telefon numaraları gelecektir.

from kisi in Kisis
join tlf in Telefons
on kisi.ID equals tlf.KisiID
select new
{
    Ad = kisi.Ad,
    Tlf = tlf.Numara
}

T-Sql çıktısı
SELECT [t0].[Ad], [t1].[Numara] AS [Tlf]
FROM [Kisi] AS [t0]
INNER JOIN [Telefon] AS [t1] ON [t0].[ID] = [t1].[KisiID]

Lambda Expression
Kisis.Join ( Telefons, kisi => kisi.ID, tlf => tlf.KisiID, (kisi, tlf) => new { Ad = kisi.Ad, Tlf = tlf.Numara } )



Senaryomuzu değiştirelim ;
Kişiler tablosundaki tüm kayıtlat gelsin, telefon numarası olmayanlar da gelsin telefonu yoksa null değer gelsin. Bunun içinde Left Outer Join ile çözeriz. Linq sorugumuzu şu şekilde değiştirmemiz yeterli olacaktır.

from kisi in Kisis
join tlf in Telefons
on kisi.ID equals tlf.KisiID into data
from x in data.DefaultIfEmpty()
select new
{
   Ad = kisi.Ad,
   Tlf = x.Numara
}

T-SQL çıktısı

SELECT [t0].[Ad], [t1].[Numara] AS [Tlf]
FROM [Kisi] AS [t0]
LEFT OUTER JOIN [Telefon] AS [t1] ON [t0].[ID] = [t1].[KisiID]

Lambda Expression
Kisis
.GroupJoin (
Telefons,
kisi => kisi.ID,
tlf => tlf.KisiID,
(kisi, data) =>
new
{
kisi = kisi,
data = data
}
)
.SelectMany (
temp0 => temp0.data.DefaultIfEmpty (),
(temp0, x) =>
new
{
Ad = temp0.kisi.Ad,
Tlf = x.Numara
}
)

 
 
Categories: C# | Code

February 8, 2008
@ 01:49 AM
Şu sıralar C# 3.0 ve LINQ ile ilgili  birçok dökümanda pek rastlamadığım bir anahtar kelimeyi (keyword) paylaşmak istedim.
Eğer LINQ ifadeleriniz içinde bir değişkene ihtiyacınız olursa - kimsenin ihtiyacı olmuyor da ondan mı kullanmıyor nedir ? ;) -
let ile tanımlayabiliriz  - bu let bir yerlerden tanıdık geliyor mu ne :)) -

Misal ;

string[] bolumler = { "matematik", "fizik", "kimya" };
Random r = new Random();

var sonuc = from c in new[]{ new {Ad="ali",Yas=21},
                                        new {Ad="murat",Yas=22},
                                        new {Ad="ismail",Yas=25}}

let bolum = bolumler[r.Next(0,bolumler.Length)]
select new
{
    Person = c,
    Bolum = bolum
};

foreach (var s in sonuc)
    listBox1.Items.Add(s.Person.Ad + " " + s.Bolum);




 
Categories: C# | Code

1.YOL Extension metodları ve lambda expression kullanarak

foreach (IGrouping<string, string> group in Directory.GetFiles(Path.GetTempPath()).GroupBy(file => Path.GetExtension(file)))
{
    listBox1.Items.Add("--- " + group.Key + " ---");
    foreach (string file in group)
    {
        listBox1.Items.Add(file);
    }
}

2.YOL LINQ Expression Kullanarak

var sonuc = from c in Directory.GetFiles(Path.GetTempPath())
                
group new
                        
{
                             DosyaAd = c
                         }
                 by Path.GetExtension(c);

foreach (var  group in sonuc)
{
    listBox1.Items.Add("--- "+group.Key+" ---");
    foreach (var s in group)
       
listBox1.Items.Add(s.DosyaAd);
}

3.YOL LINQ Expression Kullanarak (Tipler Biliniyor)

IEnumerable<IGrouping<string,string>> sonuc = from c in Directory.GetFiles(Path.GetTempPath())
                                                               
group c
                                                               
by Path.GetExtension(c);

foreach (IGrouping<string,string> group in sonuc)
{
   
listBox1.Items.Add(group.Key);
   
foreach (string file in group)
       
listBox1.Items.Add(file);
}


 
Categories: C# | Code

February 5, 2008
@ 11:22 AM
C# 3.0 dili ile birlikte gelen yeni özellikleri şimdiye kadar duymayan kalmadı denebilir. Gerek seminerler olsun gerekse Türkçe içerikli makalelerde bunlara değinildi.
Yeniliklerden birisi olan Lambda Expressionlar ile artık C# 3.0 bir "fonksiyonel programlama dilidir" diyebiliriz. İlerki zamanlarda bunlarla ilgili kod örneklerine de yer vereceğim.

Belirsiz Tiplerle (Anonymous Types) ilgili bir örnek kod olarak belirsiz tiplerden oluşan bir dizi nasıl oluştururuz buna bakalım.

	  var bilinmeyenTipdenDizi = new[] 
          {
              new {Ad="oguz",Soyad="yagmur"},
              new {Ad="sefer",Soyad="algan"},
          };

          foreach (var bilinmeyenTip in bilinmeyenTipdenDizi)
          {
              MessageBox.Show(bilinmeyenTip.Ad +" " + bilinmeyenTip.Soyad);
          }
Burda dikkat edilecek nokta dizinin bilinmeyen tipli elemanlarının aynı imzaya sahip olması. Nihayetinde bildiğimiz gibi belirsiz tiplerde IL de belirli bir tipe dönüştürülüyor ;)




 
Categories: C# | Code

January 30, 2008
@ 11:21 PM
Linq to Sql de veritabanı sunucusuna giden sorguları SQL Profiler ile izleriz. Fakat daha kolay bir yol var. Aşağıdaki resim gayet açıklayıcı ;)
Tek yapmamız gereken DataContext türünden nesnemizin Log özelliğine istediğimiz çıktıyı vermek olacaktır.



Eğer kodumuzu aşağıdaki gibi düzenlersek bu defa da üretilen T-SQL istediğimiz herhangi bir fiziksel dosyaya kaydedilecektir.

testDataContext db = new 
db.Log = new StreamWriter("C:\\l2s.log"); var v = from p in db.Persons where p.Surname == "asma" select p.Name; Text = v.First(); db.Log.Close();
l2s.log dosyasının içeriği aşağıdaki gibidir.

SELECT TOP (1) [t0].[Name]
FROM [dbo].[Person] AS [t0]
WHERE [t0].[Surname] = @p0
-- @p0: Input NVarChar (Size = 4; Prec = 0; Scale = 0) [asma]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

 
Categories: .NET | C# | Code | Inceleme

January 30, 2008
@ 12:04 AM
Birçoğuz biliyoruz ki, kimi zaman belirli bir classdan çalışma zamanında sadece tek bir nesne oluşturulmasını isteriz. Aynı sınıfa ait ikinci bir nesne oluşmasını engellemek isteriz. Bu durumda Singleton Tasarım Kalıbını (Alper Hoca'nın kulakları çınlasın)  uygularız. Fakat birçok class için bu durum geçerli ise her defasında bunu uygulamak bizim gibi üşengeç programcılar için can sıkıcı hal alır. Çözüm ise,
    
class GenericSingleton<T> where T : class, new()
{
    private static object lockObject = new object();
    private static T m_Instance;

    public static T GetInstance()
    {
        if( m_Instance != null)
            return m_Instance;
        lock ( lockObject)
        {
            if (m_Instance == null)
            {
                m_Instance = new T();
            }            
        }
        return m_Instance;
    }
}

Bu generics süper bişi! - ben bu lafı bir yerden hatırlıyorum ama -


 
Categories: C# | Code

C# 3.0'ın getirdiği güzel özelliklerden birisi olan İsimsiz Tipler'in bazı kısıtlamaları bulunmakta. Özellikle de metodlara parametre olarak geçirilme konusunda sıkıntı yaratıyor. Örneğin

static void Main(string[] args)
{
    var
v = new
    {
       
Ad = "oğuz",
        No = 44,
        Miktar = 122.2
    };
    BirDost(v);
}

şeklindeki bir tipi metoda parametre olarak geçirmek isteyelim.Amacımız bu tipin özelliklerindeki - property - değerleri almak ve işlem yapmak olsun.

public static void BirDost(var belirsizTip)
{
...
}

hmmm..işler düşündüğümüz gibi gitmeyecek ve derleyici şöyle bir  hata verecek.

Error 1 The contextual keyword 'var' may only appear within a local variable declaration

Tamam o zaman herşey object'tir mantığından yola çıkarak metodumuzu aşağıdaki gibi değiştirelim.

public static void BirDost(object belirsizTip)
{
 // belirsizTip. (???)
}

Tamam oldu gibi..Ama belirsizTip nesnesi üzerinden Ad,No,Miktar gibi özelliklere nasıl erişebilir ki? Seni seviyorum .NET diyerek biraz reflection uyguluyoruz ve sonuç.

public static void BirDost(object belirsizTip)
{
   
Type t = belirsizTip.GetType();
    PropertyInfo[] ps = t.GetProperties();

   
foreach (PropertyInfo p in ps)
    {
       
Console.WriteLine(p.Name + " => " + p.GetValue(belirsizTip,null));
    }
}

Artık isimsiz tiplerimizi gönül rahatlığı ile - çok mu duygusal oldu nedir? - metodlara parametre olarak aktarbiliriz ;)


 
Categories: C# | Code

November 14, 2007
@ 01:22 AM

Düşündüğümden daha çok kişi çalışıyormuş. Özellikle ilk sıradaki  sağdan ikinci hanımefendinin ne iş yaptığını merak ediyorum ;)

Kaynak : http://blogs.msdn.com/charlie/archive/2007/11/12/visual-c-team-picture-fall-2007.aspx

CSharpTeam.jpg (2,19 MB) (Resmin büyük hali)
 
Categories: .NET | C#

Uygulamamızda debug yaparken nesnelerimizi daha anlaşılır şekilde görmek için çeşitli Visualizerları kullanırız. Örneğin bir DataTable ya da DataSet'in içeriğini debug işlemi sırasında Visualizer yardımı ile çok daha anlaşılır bir şekilde inceleyip, doğru datalarla çalışıp çalışmadığımıza karar verebiliriz. Yeri geldiğinde XML dosyalarımızın içeriğini de daha anlaşılır şekilde görüntülemek için XML Visualizer'den faydalanırız.

Visual Studio 2005, belirli tipler için visualizerlardan yararlanabilmemizi sağlıyor. Ama bu harika IDE istenildiğinde kendi nesnelerimizi de debug işlemi sırasında özel geliştirdiğimiz bir visualizer ile gösterebilme imkanı da sağlıyor. Senaryomuz şöyle;

Uygulamamız içinde Person isimli bir türümüz var. Debug işlemi sırasında kendi geliştirdiğim Visualizer ile (aşağıdaki resimde görüldüğü üzere) bu nesneyi görüntülemek istiyorum.

Bunun için yapmamız gereken projemize yeni bir Debugger Visualizer Item'ı eklemek olacaktır. Örnek projemiz ,geliştirğimiz Visualizer'i test edecek bir Windows uygulaması (PersonVisualizerTest), Person ve türeyen nesnelerimizi barındıran bir dll (EntityObjects), ve daha sonra da kullanmak amaçlı geliştireceğimiz içerisinde kendi visualizer'imizin bulunduğu bir başka dll (PersonVisualizerLib) projesinden oluşacak.

Person nesnemiz aşağıdaki gibidir. Dikkat edecek olursanız Serializable Attribute'ü uygulanmıştır nesnemize.Yani nesnemizin geliştirdiğimiz visualizer tarafından görüntülenebilmesi için nesne serileştirilebilir olmalı.

   [Serializable()]
    public class Person
    {
        Bitmap _picture;
        public Bitmap Picture
        {
            get { return _picture; }
            set { _picture = value; }
        }

        private int _no;
        public int No
        {
            get { return _no; }
            set { _no = value; }
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

    }
 

Gelelim visualizer'imizin geliştirilmesine. DLL Projemize (PersonVisualizerLib) sağtıklayıp Add->New Item... menüsünden "Debugger Visualizer"'i şeçip tamam diyoruz.Personel nesnemizin içinde olduğu dll i projemize ekledikten sonra Visualizer'imizin kodunu aşağıdaki gibi tasarlıyoruz.

[assembly: DebuggerVisualizer(typeof(PersonVisualizerLib.PersonVisualizer),
Target = typeof(EntityObjects.Person),
 Description = "Personel Debug Ekaranı ile Göster")]

namespace PersonVisualizerLib
{
  
    public class PersonVisualizer : DialogDebuggerVisualizer
    {
        protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
        {
           
            Person person = (Person)objectProvider.GetObject();
            using (PersonForm displayForm = new PersonForm())
            {
                displayForm.person = person;
                windowService.ShowDialog(displayForm);
            }
        }
    }
}

assembly attribute'ü ile visualizer'in tip bilgisi, hangi türden nesnelerin visualizer'da görüntüleneceği, ve debug esnasında visualizer'imizin görüntülenecek adını belirtiyoruz. Show metodunun içerisinde de debug esnasında görütülenmesini istediğimiz nesneyi alıp person türüne dönüştürdükten sonra Form'a bu nesneyi görüntülemesi için veriyorum

PersonForm, nesnemin görsel olarak gösteriminde kullanacağım form nesnem. Form'un üzerinde, person nesnesini gösterecek  PropertyGrid , person nesnesinin resmini gösterecek Picturebox , person nesnesinin Name ve No  özelliklerini gösterecek iki adet Label controlü içermekte.Form'un kodu da aşağıdaki gibidir.

        public Person person;
        public PersonForm()
        {
            InitializeComponent();
        }

        private void PersonForm_Load(object sender, EventArgs e)
        {
            label1.Text = person.Name;
            label2.Text = person.No.ToString();
            pictureBox1.Image = person.Picture;

            propertyGrid1.SelectedObject = person;
        }

Tüm bu hazırlıklardan sonra visualizer'i test edeceğim projeme Person nesnesinin içinde olduğu Dll'i ekliyorum. Visualizer'imizin VS.NET 2005 tarafından işlem görebilmesi için oluşan PersonVisualizerLib.dll 'ini C:\Documents and Settings\{user_name}\My Documents\Visual Studio 2005\Visualizers dizinine kopyalıyoruz. Artık kendi geliştirdiğimiz tüm uygulamalarda bu visualizer'i kullanabiliriz. Ama makina düzeyinde tüm kullanıcıların'da bu visualizer'den yararlanmasını istiyorsak ilgili dll'i C:\Program Files\Microsoft Visual Studio 8\Common7\Packages\Debugger\Visualizers dizinine kopyalamanız yeterli olacaktır.

Artık debug esnasında oluşturğumuz visualizer ile Person nesnemizi tasarladığımız şekilde görebilmek mümkün olacaktır.

Tabiki bu örnek dışında, örneğin geliştirdiğiniz bir asp.net uygulamasında ürün sepeti'nizi bir grid içinde görüntülemekten tutun, bir stream nesnesini istediğiniz formatta görüntülemeye kadar birçok özel visualizer geliştirerek debug işlemlerini hem kolaylaştırıp hem de daha zevkli hale getirmek mümkün :=)

PersonVisualizerTest.rar (43,77 KB) (Bahsi geçen örnek uygulama ektedir.)
 
Categories: .NET | C# | Inceleme

Msdn'de soldaki TreeView'de StackTrace sınıfını incelemek isterken hemen altında bulunan StopWatch sınıfı isminden dolayı baya bir gözüme battı. Neymiş diye incelerken çoğumuzun bir kodun ne kadar süre çalıştığını test etmek için DateTime.Now ile o anki zaman değerini alıp kod bitiminde Datetime.Now ile zaman değerinden bir önceki değeri çıkarma işlemini yaparız. StopWatch sınıfı ile çok daha hassas ve kesin ( Daha alt sistem API'lerini kullandığınu söyledi google ;) ) değer alabiliyormuşuz. Kullanımına dair örnek kod aşağıda.

private void button1_Click(object sender, EventArgs e)
{
   System.Diagnostics.Stopwatch diff = new System.Diagnostics.Stopwatch();
   diff.Start();
   for (int i = 0; i < 2000000; i++)
   {
      int x = i >> 2 << 22 >> 222 << 2222 >> 22222 << 222222;
   }
   diff.Stop();
   label1.Text = diff.Elapsed.ToString();
}       

DateTime ile aynı kodu şu şekilde test ettim.

long t = DateTime.Now.Ticks;
for (int i = 0; i < 2000000; i++)
{
   int x = i >> 2 << 22 >> 222 << 2222 >> 22222 << 222222;
}
long t1 = DateTime.Now.Ticks;
label1.Text = (t1 -t).ToString();

Sonuç ya 0 (yazı ile sıfır) ya da 156250 iken aynı kodu StopWatch sınıfını kullanarak test ettiğimde 28400 ile 28800 arasında sonuçlar verdi.
 
Categories: C# | Code | Inceleme

Debug işlemleri yaparken sıklıkla karşılşatığımızın durumların başında nesnemiz başka bir nesneyi içeriyorsa bu nesneyi ancak hiyeraşik bir biçimde inceleme şansına sahip oluyoruz. Aşağıdaki resimde daha net birşekilde ne demek istediğim belli oluyor.

Görüldüğü gibi Report nesnemiz içerde List<int> türünden Results özelliğine (property) sahip. Bu özelliğin hangi değerlerini tuttuğunu görmek için + ile detayına inip bakmamız gerekiyor. Bu özellik baska bir nesneyi temsil ediyor, ve o nesne de içerisinde iç içe (nested ) başka değerleri tutuyor olabilir. Bu durumda + lar ile detaylara inip boğulabilirsiniz ;-) Ama çoğumuz bu iç içe nesnelerin aslında sadece işimize yarayacak kısmını debug işlemi sırasında görmek isteyebilir, hatta bu kısımları özelleştirerek istediğimiz gibi bir görüntü sağlayabiliriz. Aşağıdaki resim ile bir önceki resimi kıyaslayarak debug işlemi sırasındaki görüntüleri karşılaştırabilirsiniz.

Bu görüntünün sağlabilmesi için yapmamız gereken Report nesnemizin debug işlemi sırasında görünmesini isteyeceğimiz şekilde bir proxy class'ını hazırlamak.

[DebuggerTypeProxy(typeof(ReportDebuggerProxy))]
    public class Report
    {
        private DateTime _date;
        public DateTime ReportDate
        {
            get { return _date; }
            set { _date = value; }
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        private List<int> _results = new List<int>();
        public List<int> Results
        {
            get { return _results; }
            set { _results = value; }
        }

        private int _dummy;
        public int Dummy
        {
            get { return _dummy; }
            set { _dummy = value; }
        }

    }

Report nesnemize DebuggerTypeProxy attribute'nün uygulandığı dikkatinizi çekmiştir. Bu atrribute sayesinde Report nesensi debug işlemi sırasında sanki Report türünden bir nesne değil de ReportDebuggerProxy nesnesinin bir görüntüsüymüş gibi karşımıza çıkacaktır. Şimdi proxy görevini görecek sınıfımızı yazalım.

public class ReportDebuggerProxy
    {
        Report _report;
        public ReportDebuggerProxy(Report report)
        {
            _report = report;
        }

        public string ReportDate
        {
            get { return _report.ReportDate.ToLongDateString();}
        }
        public string Name
        {
            get { return "Raport Name : " + _report.Name; }
        }

        public string Results
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                foreach (int result in _report.Results)
                {
                    sb.Append("(");
                    sb.Append(result.ToString());
                    sb.Append(") ");
                }
                return sb.ToString();
            }
        }
    }

Görüldüğü gibi debug sırasında görmek istediğimiz özellikleri belirtiyoruz. Proxy sınıfında dikkat ederseniz Report sınıfındaki Dummy özelliğine yer verilmemiş ve diğer özellikler ise görülmek istendiği şekilde özelleştirilmiş.

 


 
Categories: .NET | C# | Inceleme

Debug işlemleri yaparken yeri geldiğinde bir o kadar yararlı ve zaman kazandırıcı özellikleri  çoğunlukla gözden kaçırıyoruz. Oysa yapmamız gereken breakpoint üzerine sağ tıklamak ve özellikleri incelemek.

Condition : Eğer belirli bir duruma göre debug işlemini gerçekleştirmek istediğinizde bu özelliği aktif hale getirebilirsiniz. Aşağıdaki kod üzerinden örnek vermek gerekirse; Do metodunda dummyValue değişkenin değeri 22 ise debug işleminin aktif hale gelmesini istersem ;

gibi bir Condition eklemem yeterli olacaktır. Eğer dummyValue 22 den farklı bir değer ise debug işlemi sırasında breakpoint yokmuş gibi işlem görecektir. BreakPoint'e bir Condition eklediğinizde breakpoint'in ikonunun değiştiğini göreceksiniz. Bu kısımda da  otomatik isim tamamlama özelliğinin aktif olması harika birşey!

Hit Count : Debug işlemi sırasında o ana kadar kaç defa breakpoint'e gelindiğini takip edebiliriz.İsterseniz de "eğer bu breakpoint'e x kadar gelindiğinde artık debug işlemi yapılmasın" da diyebilirsiniz. (Açılan dialog penceresindeki combobox'dan diğer seçenekleri inceleyiniz.)

Filter : Belirli filitreler koyarak debug işlemlemini aktif hale getirebiliriz. Aşağıdaki resimde hangi filitreleri uygulayacağımız açıklanıyor zaten. Bunlar dışında bir filitre uygulamak istediğinizde buna izin verilmediğini göreceksiniz.Örneğimizdeki filitrede eğer bu metod "debugTest" isimli Thread tarafından çağrılmışsa debug işlemi aktif hale gelecektir.

When Hit... : Debug işemi aktif hale geldiğinde isterseniz Output Window'a durum bilgilerini yazdırabilir, isterseniz de VS.NET 2005'e ait çeşitli makrolardan birini çağırabilirsiniz. Örneğimizde breakpoint'in hangi metod içinde olduğunu ve bu metodu kimin çağırdığını yazdırıyoruz. Ardından da o satırı yorum satırı haline getiren bir makroyu çalışrırıyoruz.

 

Tanımlamarımızı yapıp debug modunda uygulamamızı çalıştırdığımızda aşağıdaki gibi bir sonuç alıyoruz.

public Form1()
{
    InitializeComponent();
    CheckForIllegalCrossThreadCalls =
false;
}
private void button1_Click(object sender, EventArgs e)
{
    DoOp();
}

public void DoOp()
{
   
Thread th = new Thread(Do);
    th.Name =
"debugTest";
    th.Start();
}

int dummyValue = 22;
public
void Do()
{
   
for (int i = 0; i < 5; i++)
    {
         Text = i.ToString(); //Breakpoint konulan satır
    }
}

 


 
Categories: .NET | C# | Inceleme

September 3, 2007
@ 10:22 PM

Debug işlemleri yaparken işimize yarayacak 3 adet Attribute'ü aşağıdaki örnek üzerinden incelersek ;

DebuggerDisplay attribute'ü ilgili sınıfdan nesne örneğini incelediğimizde debug penceresinde istediğimiz şekilde görünmesini sağlayabiliriz.

DebuggerStepThrough  attribute'ü ile de F11 ile kod debug edildiğinde bu kod satırların debug işlemi sırasında dikkate alınmayacağını belirtir. Örneğin

Ogrenci o = new Ogrenci();
o.Name = "ali";
o.No = 22;

gibi bir kod satırında o.Name="ali"; satırında iken F11 'e bastığımızda Name özelliğinin set metoduna dallanacağını biliyoruz. Fakat DebuggerStepThrough attribute'ü set için uygulandığından bu dallanma gerçekleşmeyecek o.No=22 satırından itibaren debug işlemi devam ecektir. (Laf aramızda süper bir atrribute'müş kendisi yahu ;) )

DebuggerBrowsable isminden de açıkça belli olduğu üzere bu attibute'ün uygulanmış olduğu nesnenin X özelliği debug ekranında görüntülenmeyecektir.

 

[DebuggerDisplay("Ad ={Name},No = {No}")]
public class Ogrenci
{

   private string _name; 
   public string Name
   {
      [DebuggerStepThrough]
      get { return _name; }

      [DebuggerStepThrough]
      set { _name = value; }
   }

   private int _no;
   public int No
   {
      get { return _no; }
      set { _no = value; }
   }
   private int _x;
   [DebuggerBrowsable(DebuggerBrowsableState.Never)]
   public int X
   {
      get { return _x; }
      set { _x = value; }
   }
}


 
Categories: .NET | C#

August 24, 2007
@ 07:00 PM

public IEnumerable<int> GetRandomNumbers(int min, int max, int count)
{
    Random r = new Random();
    for (int i = 0; i < count; i++)
    {
        yield return r.Next(min, max);
    }
}

private void button1_Click(object sender, EventArgs e)
{
    listBox1.Items.Clear();
    foreach (int x in GetRandomNumbers(10, 50, 15))
        listBox1.Items.Add(x);
}


 
Categories: C#

August 24, 2007
@ 06:52 PM

500 sayfalık C# 3.0 dili spesifikasyon dökümanı (*.doc) şurdaki adresten doğrudan indirebilir,şurdaki adresten de diğer dökümanlara erişlebilirsiniz.


 
Categories: C#

C# kodlarını VB.NET'e, VB.NET kodlarını da C#'a çeviren sayfa için linki ziyaret ediniz ;)

Please visit the following link to convert the C# codes to VB.Net and VB.Net codes to C# ;)

 


 
Categories: .NET | C#

.Net Akademi eğitiminden bir ders çalışması...

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Collections;

namespace sortedbyProperty
{
    class Program
    {
        static void Main(string[] args)
        {
            HedeColl h = new HedeColl();

            h.Add(new Ogrenci(2, "ali", DateTime.Now.AddDays(10)));
            h.Add(new Ogrenci(21, "ahmet", DateTime.Now.AddDays(1)));
            h.Add(new Ogrenci(12, "mehmet", DateTime.Now.AddDays(122)));

            h.Sortla("Tarih",BuyukKucuk.Buyuk);

            foreach (Ogrenci o in h)
            {
                Console.WriteLine(o);
            }
        }
    }


    enum BuyukKucuk
    {
        Buyuk,
        Kucuk
    }
    class HedeColl : List<Ogrenci>
    {
        public HedeColl()
        {
          
        }

        public void Sortla(string pad, BuyukKucuk siralama)
        {
            this.Sort(

                delegate(Ogrenci o1, Ogrenci o2)
                {
                    PropertyInfo prop1 = o1.GetType().GetProperty(pad);
                    PropertyInfo prop2 = o2.GetType().GetProperty(pad);

                    object v1 = prop1.GetValue(o1, null);
                    object v2 = prop2.GetValue(o2, null);

                    int val = Comparer.Default.Compare(v1, v2);
                    if (siralama == BuyukKucuk.Kucuk)
                        return val;
                    else
                        return -val;
                }
            );
        }
    }

    class Ogrenci
    {
        private int _no;
        public int No
        {
            get { return _no; }
            set { _no = value; }
        }

        private string _ad;
        public string Ad
        {
            get { return _ad; }
            set { _ad = value; }
        }

        private DateTime _tarih;
        public DateTime Tarih
        {
            get { return _tarih; }
            set { _tarih = value; }
        }

        public Ogrenci(int a, string b, DateTime d)
        {
            Ad = b;
            No = a;
            Tarih = d;
        }

        public override string ToString()
        {
            return String.Format("Ad :{0} No : {1} Tarih : {2}", Ad, No, Tarih);
        }

    }
}


 
Categories: C# | Code

BT Akademi'nin değerli eğitmenlerinden Özcan Değirmenci'nin BT Akademi'de verdiği WinForm 2.0 Akademideki örnekleri incelerken  bol bol  StructLayout  attribute'leri ile  karşılaşıyorum . Malum  Windows API seviyesinde kod  yazmayan  geliştiricilerin pek ihtiyaç duymadığı hatta birçoğunun haberi dahi olmadığı ama kontrol geliştiren, ciddi manada detaylı windows uygulamaları geliştirenlerin - örneğin .NET Framework'ün desteklemediği sistem fonksiyonlarının kullanıldığı - sıklıkla kullandığı bu attrribute sayesinde class'ların yada structların - kısaca Type'ların - memory'de istenilen şekilde yerleşmesini sağlayabiliyoruz.

Herhangi bir Type bildirimi yapıldığında CLR performans sağlanması adına bu Type'ın üye elemanlarının memory'deki yerleşim düzenini kendisi ayarlamaktadır. Bu şekilde hem daha az memory kullanımı optimize ediyor hem de ilgili Type'ın üye elemanlarına erişim hızının artırılmasını sağlıyor. Fakat bazı Windows API fonksiyonları bizden parametre olarak özel bir şekilde memory'de  dizilmiş struct isteyebiliyor. Bu durumda memory'deki dizilimini CLR'nin değil de bizim yapmamız gerekiyor. İşte burda StructLayout attribute'ü tüm ihtiyacımızı karşılıyor. LayoutKind numaralandırıcısını (Enumeration) kullanarak dizilimi kendimiz beliryebiliyoruz.

Not : Struct tanımladığınızda otomatik olarak bu özellik Sequential'dir. Ama bu attribute'ü bir class için kullanmak isterseniz mutlaka LayoutKind.Sequential numaralandırıcısını kullanmalısınız.

Auto : CLR'nin yaptığı gibi
Sequential : Sıralı bir şekilde aynen bildirimdeki sıraya göre
Explicit : Biz nasıl istiyorsak öyle.

[StructLayout(LayoutKind.Sequential)]
public struct Coord
{
     int x;
     int y;
}

gibi..Eğer bu dizilimin bizim isteğimize göre olmasını istersek de LayoutKind.Explicit numaralandırıcısını aşağıdaki gibi kullanmalıyız.

[StructLayout(LayoutKind.Explicit)]
struct Coord
{
     [FieldOffset(0)]
     public int x;
     [FieldOffset(4)]
     public int y;
}

Üye elemanlarına FieldOffset attribute'ünün uygulandığını görüyoruz. Bu sayede memory'de hangi elemanın hangi offsetten -kaçıncı byte'dan - itibaren yerleşeceğine karar  verebiliyoruz. Yukardaki örnekte yapımızın 0. byte'ından itibaren x'in yerleşeceğini, 4.byte'dan itibaren de - sizeof(int) de kullanabilirsiniz. int'in büyüklüğü kadar memoryde ilerlemek için - y'nin yerleştirileceğini belirtebiliyoruz. Bu özellik sayesinde aslında çok az memory kullanarak struct yapımızın içinde çok sayıda üye eleman tanımlayabiliriz. Yapmamız gereken tekşey tüm üye elemanlarımızın 0. offsetten itibaren memory'ye yerleşmelerini sağlamak.

[StructLayout(LayoutKind.Explicit)]
struct Coord
{
    [FieldOffset(0)]
    public int x;
    [FieldOffset(0)]
    public int y;
    [FieldOffset(0)]
    public long z;
}

---- x
---- y
---- ---- z
Bu sayede 8 byte'lık bir alanda 2 int bir de long türünden değişken saklayabiliyoruz ;) C 'deki union yapısına baya bir benzedi değil mi? Ha dersiniz ki ben gittim z ye 12 değerini atadım sonra gittim x'e 22 değerini atadım z'nin değeri şimdi ne oldu ? Bilmem ne oldu ? :) Aşağıdaki kodu biraz kurcalamakda fayda var.

public class Test
{
     static void Main(string[] args)
     {
         Coord c = new Coord();
         c.z = 2000000000;
         c.x = 20;
         Console.WriteLine(c.z);
     }
}

[StructLayout(LayoutKind.Explicit)]
struct Coord
{
     [FieldOffset(0)]
     public int x;
     [FieldOffset(0)]
     public int y;
     [FieldOffset(0)]
     public long z;
}



 
Categories: .NET | C# | Code | Inceleme

September 17, 2006
@ 12:00 AM
Olur da windows service yazmak istersiniz, olur da bir başka uygulamadan bu servise komut göndermek için ServiceController'ın ExecuteCommand(int command) metodunu kullanırsınız, olur da parametre olarak metoda 128 den küçük 256 dan büyük bir sayı göndermeyi isteyebilirsiniz. İşte orda duracakmışız. Neden ? Çünkü alınan hata "bu servis bu bilgisayarda yönetilemez"dir. MSDN şurada der ki; bir servise komut gönderecekseniz bu komut 128 ila 256 arasındaki değerler olmalıymış.O zaman işlerimiz tıkırında gidermiş.

(The only values for a custom command that you can define in your application or use in OnCustomCommand are those between 128 and 256. Integers below 128 correspond to system-reserved values.)
 
Categories: C#

Bu düşünce ile yola çıkan bir grup var.Projenin  ismi de Singularity. Şu anda araştırma aşamasında olan bir proje. Yani olur mu olmaz mı bunu araştıryorlar. Donanım ile uygulamaları birbirinden izole etmek üzerine çözüm arıyorlar.
Belkide Microsoft, işletim sistemlerinin güvenliğini tamamen sanal makina gibi çalışan bir işletim sistemi ile çözmek istiyor olabilir. Uygulamarın kodları direk donanıma erişmediği bir sistemde açıkdan bahsedilebilir mi ki?
CLR gibi sanal bir sisteme bu kadar önem veriyor olmasının, AR-GE sinin büyük bir bölümünü .Net gibi managed kodların çalıştığı ortama kaydırmış olmasının bir açıklaması olmalı.


Detaylı bilgiyi projenin sayfasından edinebilirsiniz.


 
Categories: C#