www.cihansalim.net
site içindeİnternet'te

 Dergi Yazıları
   
"COM ve .Net Projeleri Arasında Entegrasyon"

Microsoft'un eski platformu COM'da çalışanlar .Net'e geçişte bazı sorunlar yaşıyor. Ama aslında iki platform arasında nesneleri taşıyıp eski işlevselliğinize kavuşmak son derece basit.

Hepimizin hatırlayacağı gibi Microsoft bir zamanlar
tıklayın, destekleyin:
İnternet'e gereken önemi vermiyordu, bu nedenle de çok eleştiriliyordu. Tilki Gates ve kurmayları meğerse sadece doğru zamanı arıyorlarmış. Zaten, bazıları biraz geç kalmış olsa da, gerekli adımların çoğunu atmış olduklarını bugünkü duruma bakınca görebiliyoruz.

Microsoft dünyasında uzun bir süre egemen kalan perpektiflerden ve de doğru atılmış adımlardan biri de COM platformu idi. Fakat artık kimse "COM"u hatırlamıyor. Bunun bir nedeni de tabii ki Microsoft'un yeni .Net vizyonu. .Net, gerçekten de COM'un ardından büyük bir değişim, yeni bir ortam sunuyor. Ve Microsoft'ta yıllarca etkili olan COM'dan gerçek anlamda çok ileri bir aracımız var artık.

Tabii .Net'in getirdikleri sayesinde birçok şey eskiye oranla daha hızlı ve kolayca kurulabiliyor ama ya siz eski bir COM kullanıcısı iseniz ne yapmayı planlıyorsunuz? Her şeyi .Net ile pek zaman kaybetmeden yeniden yapabiliyorum deseniz de tabii ki COM'dan kalan bazı pratik uygulamalarınızı .Net'e alıp daha verimli olmanız en mantıklısı. Hem de bu sanıldığı kadar zor değil.

Bir adım ilerde .Net
COM bileşenleri ile .Net derleyicileri her ne kadar aynı Dynamic Link Library'leri (DLL) kullanabiliyor olsa da aslında dahili açıdan işler öyle değil. Bir .Net derleyicisi bilgilerini 'registry'de tutma gereği duymuyor, onun yerine tür, vb. bilgilerini "meta veri" şeklinde tutuyor. Zaten bu meta veri de derleyicinin için de mevcut durumda. Bunun da ötesinde .Net derleyicisi, COM nesnelerinin tümü tarafından kullanılan bir arabirim olan IUnknown arabirimini temel almıyor.

COM ile .Net arasında uyum sağlama örneği verdiğim bu yazıda şunu da belirteyim ki .Net terimlerinin önemli bir çoğunluğu henüz "Microsoft Türkçesi"'ne çevrilmedi, en azından benim elimde böyle bir terim kaynağı yok. O yüzden bu yazıda bazen orijinal terimleri, bazen de Türkçelerini kullanmayı seçtim. Örneğin COM içinde yer alan kodları "düzenlenmemiş" olarak tanımlamayı tercih ediyorum.

.Net çatısı altında yer alan kodlar "Ortak Dil Çalışma Zamanı"na göre düzenlenmiş oluyor, bu nedenle de .Net kodları düzenlenmiş kod iken böyle bir düzenlemeden geçmeyen COM kodları düzenlenmemiş durumda. Ama tabii COM formundaki bir kodda oldukça yararlı işlevler olabiliyor ve bunları tek tek .Net'e uyarlamak pek de pratik değil.

Henüz yeni bir platform olan .Net için varolan kodlar COM kodlarından daha az sayıda. İşte bu nedenle de iki platform arasında bir bağ kurmak en akıllıcası.

COM nesnelerini .Net'e çağıralım
COM ile .Net arasında gömülü bir uygulama kurmanın avantajları açık, zaten bu nedenle de .Net çatısı altında bu göreve atanmış bir "ad alanı" mevcut. System.Runtime.InteropServices ad alanı bize .Net'den COM nesnelerine ulaşabileceğimiz yeni sınıflar sunuyor.

Bir COM nesnesi içerisindeki kod Ortak Dil Çalışma Zamanı tarafından kullanılmadığından .Net'e geçiş de farklı bir yol izliyoruz. COM nesnesi bir kapsayıcı sınıf içerisindedir. Bu kapsayıcı, COM nesnesini bir .Net derleyiciymiş gibi Ortak Dil Çalışma Zamanı'na açar. Kapsayıcı "Çağrılabilir Çalışma Zamanı Kapsayıcısı" olarak adlandırılıyor, orijinal adıyla da, Runtime Callable Wrapper (RCW). Bu süreç alttaki şema da görülebilir.

COM nesnelerini .Net geçirmemizde en büyük yardımcımız RCW'ler. RCW'ler yeni platformun eski nesneleri tanımasını ve işletebilmesini sağlıyor
Bu kapsayıcı sınıf (RCW), düzenlenmiş kod ile düzenlenmemiş kod arasında bir köprü görevi görüyor ve tüm operasyonlar bu sınıfların yolundan yönlendiriliyor. Şimdiye kadar COM ile .Net arasındaki kod ve işleme farkını teoride inceledik, artık bir örnekle bu aşamaları inceleyelim.

Visual Studio.NET ile gömme işlemi
"Çağrılabilir Çalışma Zamanı Kapsayıcısı" oluşturma işlemi otomatik olarak Visual Studio.NET tarafından yapılabiliyor. İlk önce böyle bir gömme işlemi deneyelim. Diyelim ki uygulamamızda Microsoft Excel programını kullanmamız gerekli. O zaman "Project" menüsünden "References"a tıklayıp COM 'tab'ına geçeriz. COM sayfasında da "Microsoft Excel Object Library" seçeriz.

Excel nesne kitaplığını seçip OK'e basar basmaz Visual Studio.NET bir RCW hazırlayacak. İsimlendirme aşamasında ise "Interop.COMObject.dll"den yararlanacak. Bu durumda RCW'miz de "Interop.Excel.dll" adını alacak. .Net uygulamasında da buna bir referans eklenmiş olacak, böylece Excel nesnelerini hemen kodumuzda kullanabileceğiz. Aynı durum, sizin yazmış olduğunuz tüm COM bileşenleri için de geçerli olacak. Burada dikkat edilmesi gereken tek nokta, söz konusu COM bileşenlerinin önceden 'registered' olması.

.Net'den aynı zamanda ActiveX kontollerini de kullanabilirsiniz. Bunun için boş bir alana tıklayıp Toolbox'ınızı özelleştirme ekranına ulaşmanız gerekiyor. COM Components 'tab'ından örneğin "Microsoft ListView Control"'ü ve tabii istediğiniz diğer bileşenleri işaretli hale getirin. Böylece Listview kontrolü toolbox'ınıza eklenmiş olacak.

Bir Listview kontrolünü istediğiniz yere yerleştirince Visual Studio.NET, ActiveX kontrolü için gereken RCW'yı hazırlayacak. Bu sefer de adlandırma prosedüründe "AxInterop.ActiveXControl.dll" kullanılacak. Bu doğrultuda da "AxInterop.MSComctlLib.dll" yeni isim olacak.

Visual Studio.NET kullanmadan gömme işlemi
Çeşitli nedenlerden dolayı Visual Studio.NET kullanmıyor olabilirsiniz, o zaman .Net çatısı altında bir olasılık daha var. O da "tlbimp.exe" ile çalıştırdığımız "Tür Kitaplığı Alma Programı". Bu araç sayesinde COM kitaplığı içerisinde tür tanımlamalarını bir .Net derleyicisine çevirebilirsiniz.

Örneğin COM altında ürettiğimiz bir DLL olsun, adı da "COMbilesenim.dll". Tür Kitaplığı Alma aracında şu komutla bir RCW kurabilirsiniz:
Tlbimp COMbilesenim.dll /out:bilesenimRCW.dll
ActiveX kontrolleri içinse yine .Net çatısı içerisinde gelen araçlardan biri olan "ActiveX Importer" (aximp.exe) kullanılabilir. ActiveX kontrolü içerisindeki tür tanımlamalarını bir Windows Form Kontrolüne çevirebilirsiniz. O zaman da komut satırında şu komutu vermeliyiz:
Aximp benimOCX.ocx

RCW'ler nasıl elde ediliyor
.Net ile oldukça haşır neşir olanlar Visual Studio.NET'in ya da komut satırında kullandığımız araçların bu kapsayıcıları nasıl ürettiğini merak etmişlerdir. İşte olayın anahtarı:

.Net iskeletinde yer alan sınıf kitaplığı içinde özel bir sınıf var. "TypeLibConverter" isimli bu sınıf hiyerarşi olarak System.Runtime.IneropServices.TypeLibConverter anahtarında bulunabilir. İşte söz konusu bu sınıf, "ConvertTypeLibToAssembly" adlı metottan yararlanıyor. Bu metot ile RCW'ler üretiliyor ve tabii bu metotu siz de kendi araçlarınızı yazmak için kullanabilirsiniz.

Aynı şey ActiveX kontrolleri için de geçerli. "AxImporter" sınıfı (System.Windows.Forms.Design.AxImporter) yine kendi RCW'lerinizi ActiveX kontrolleri için üretmenizi sağlayacaktır.

.Net ile COM temelleri arasındaki önemli ana farklardan bazıları tabii ki de mimari değişiklikler. Bellek kullanımındaki farklılık buna iyi bir örnek. Ortak Dil Çalışma Zamanı, bir çöpçü gibi gereksiz ya da süresi dolan parçacıkları bellekten temizleyip, bellek paylaşımını ve boşaltımını otomatik bir şekilde idare ediyor. Bu otomatik yönetim belli periyotlarda yapılıyor. Böylece bir nesne, Visual Basic.NET'de "Nothing", C#'da "Null" olarak sabitlendiğinde ya da faaliyet alanının dışında çıktığında yanlışlıkla yok edilmemiş oluyor.

Bir RCW ise bu olasılıklardan biriyle karşılaşırsa hemen yok edilmiyor, onunla ilgili olan COM nesnedi de bellekte bir süre daha kalıyor ki bu da pek hoş bir durum değil. Böyle durumlarda belleği boşaltmak için bizim bazı şeyler yapmamız yararlı olabilir. Örneğin "çöpçümüzü" kullanabiliriz, yani "System.GC.Collect" metodunu çağırırız. Ya da daha çok tercih edilen şekilde RCW'deki "Marshal.ReleaseComObject" metodunu çağırabiliriz.

Peki .NET'de yaptıklarımızı COM'a nasıl taşıyabiliriz? InterOp kullanırken nelere dikkat edeceğiz?
Dosya Devam Ediyor
» 2. sayfa »