Ana içeriğe atla

AppDomain Sınıfı ile Müşteri İhtiyaçlarının, Dinamik Kod Üretilerek Karşılanması

Günümüz iş uygulamalarında, artan ihtiyaçlar doğrultusunda yazılım geliştiriciler olarak bizler, ihtiyaçları karşılamak için pek çok farklı tasarım modellerini hayatımıza sokmak zorunda kalıyoruz. Bu modellerden son zamanlarda en popüler olanı ise .Net altyapısını kullanarak CodeDom sınıfı ile dinamik kod üretip, üretilen kodun uygulamada dinamik çalıştırılmasıdır. Böylece, müşteriden müşteriye değişen ihtiyaçlar nedeniyle, parametrik yapılarla uygulamanın çatısını bozabilecek seviyeye gelebilen değişikliklerin önüne geçmiş oluyoruz.
Peki, CodeDom sınıfını kullansak da kullanmasak da, bir şekilde dinamik oluşturduğumuz kodu çalıştırmak istediğimizde ne gibi problemlerle karşılaşırız?
.Net altyapısında dinamik oluşturulan dosyalar, aynı uygulama tarafından bir kez yüklendiğinde bellekten boşaltma şansınız kalmaz.
Eğer uygulamanız özellikle sistem kaynaklarına çok ihtiyaç duyan bir uygulama ise (web uygulaması gibi) bu durumda dinamik oluşturulan kodlarınızı belleğe yükleyip, kullanıp, işiniz bittiğinde de kaldırmak durumunda kalırsınız. İşte tam bu noktada da AppDomain sınıfı devreye girer. AppDomain sınıfı, çalıştırılan uygulamalar için izole bir ortam oluşturmanızı sağlayan diğer bir deyişle .Net uygulamaları ile kendi içerisinde kullandığı .net assembly dosyalarının birbirinden bağımsız çalışmasını sağlayan bir sınıftır. Avantajlarını sıralamak gerekirse;
  • Yüklenen dosyaların bellekten boşaltılmasını sağlar.
  • Dinamik oluşturulan kodlarınız çalıştırıldığında oluşabilecek herhangi bir kararsızlık anında, ana uygulamanız bundan hiç etkilenmeden, yaratmış olduğu AppDomain kopyasını silerek çalışmasına kaldığı yerden devam eder.
Örnek Senaryo ve Kodlaması:
Uygulamanız tarafından belirlenen bir dizin içerisinde oluşturulan dinamik kod dosyalarının yüklenmesi, çalıştırılması ve bellekten atılması…
Burada, “belirlenen bir dizin” in altını çizmek zorundayız çünkü eğer uygulamanız bir web uygulaması ise, çalışma anında “Bin” dizini altında yapılacak herhangi bir dosya işlemi, IIS tarafından izlendiği için uygulamanızın sonlanmasını tetikler. Bunu önlemek için, derlenen dosyaların, yine web uygulamanızın erişebildiği farklı bir dizinde olması gerekmektedir. Böyle bir dizin, yine uygulamanızın kök dizini altında olup, “Bin” dizini ile aynı seviyede olabilir.
AppDomain kullanımı için öncelikle, AppDomainSetup nesnesinden bir kopya yaratmanız gerekir. Sonrasında ise özelliklerinin verilmesi gerekmektedir. Bu sınıfta öne çıkan özellikler aşağıdaki gibidir:
  • ActivationArguments:.Net manifest tabanlı modeli belirler. Uygulamanın bağımlı olduğu dosyalar, güvenlik gereksinimi vs gibi uygulamanın çalışması için gereken bilgileri içerir.
  • ApplicationBase: Uygulamanın bulunduğu dizini gösterir.
  • PrivateBinPath:AppDomain nesnesinin, çalışma anında arama yapacağı dizinleri belirler. “;” ayıraç ile birden fazla dizin verilebilir.
AppDomain.CreateDomain(“HerhangiBirIsim”,AppDomain.CurrentDomain.Evidence,ads);
Burada ikinci parametre için kodu çalıştıran ortamın “Evidence” nesnesi veya “null” değer geçirilebilir. Her iki durumda da, kodu yaratan ortamın kimlik bilgisi kullanılmış olur. Son olarak da, derlenen kodu çalıştırmak için gereken kodun yazılması gerekir.
ICodeExecution execCode = workerAppDomain.CreateInstanceAndUnwrap(fAssemblyNameWithNoExt, String.Concat(fDefaultNameSpace, ".", fClassNameToInvoke)) as ICodeExecution;
execCode.DoExecute(ref executionParams);
Burada CreateInstanceAndUnwarp fonksiyonuna, yaratılan assembly nin dosya uzantısı haricindeki adı ve yaratılacak nesnenin tam adı (bulunduğu isim uzayı [namespace] ve sınıf adı) parametre olarak geçirilir. Dönen nesne ise, her iki “AppDomain” in (kodun çalıştırıldığı ve yaratılan) bildiği bir arayüze tip dönüşümü ile kullanılabilir. Dolayısıyla burada bazı dikkat edilmesi gereken noktalar vardır;
  • Hem derlenen assembly nin referanslarında hem de uygulamamızda kullanılmak üzere hazırlanması gereken bir dll ve bu dll içerisinde tip dönüşümü için kullanacağımız bir arayüz (örn: ICodeExecution) olmalıdır. Bu arayüz üzerinde tanımlı yordam ve özellikler üzerinden “AppDomain” ler arası veri alışverişi gerçekleşir.
public interface ICodeExecution
{
  void
DoExecute(ref object[] executionParams);
}
Ana uygulamadan yaratılan “AppDomain”e çalıştırma anında parametre geçirilmesi gerekiyorsa (örn : object[] executionParams), “Serializable” olarak işaretlenmelidir.
[Serializable]
public
class ExecutionParams
{
private
int result = 0;
public int Value1 { get; set; }
 public int Value2 { get; set; }

public void CalculateResult()
  {
      result = Value1 + Value2;
   }
  public int GetResult()
  {
      return result;
   }
}
  • Ek olarak bu arayüzü kullanan soyut bir sınıfımızın olması dinamik kodlamanın yapılacağı sınıfın altyapısını oluşturmamızı kolaylaştırır. İki farklı “AppDomain” in .Net remoting ile haberleşmesi için gereken tanımlanın bu soyut sınıfta yapılması, dinamik kodlamanın yapılacağı sınıfların da bu soyut sınıftan türetilmesi daha kolay ve hatasız kod oluşumuna olanak sağlar. Dolayısıyla sınıf, MarshalByRefObject nesnesinden türetilmeli ve yukarıda belirtilen ICodeExecution arayüzünü kullanmalıdır.
public abstract class CodeExecution : MarshalByRefObject, ICodeExecution
{
   #region
[_PUBLIC_]
   public CodeExecution() { }
   #region
..ICodeExecution Members..
   public abstract void DoExecute(ref object[] executionParams);
   #endregion
  #endregion
}
Tam kod aşağıdaki gibidir, her iki tarafta kullanılan “ScriptingContracts.dll” içeriği:
public abstract class CodeExecution : MarshalByRefObject, ICodeExecution
{
   #region [_PUBLIC_]
   public CodeExecution() { }
   #region
..ICodeExecution Members..
   public abstract void DoExecute(ref object[] executionParams);
   #endregion
   #endregion
}
public interface ICodeExecution
{
    void
DoExecute(ref object[] executionParams);
}
[Serializable]
public class ExecutionParams
{
  private int result = 0;
  public int Value1 { get; set; }
  public int Value2 { get; set; }
  public void CalculateResult()
  {
    result = Value1 + Value2;
  }
  public int GetResult()
  {
    return result;
 
}
}
Uygulamamızda olması gereken çalıştırma kodu:
AppDomain workerAppDomain = null;

try
{
      
AppDomainSetup
ads = new AppDomainSetup();
       ads.DisallowBindingRedirects = false;
       ads.DisallowCodeDownload = true;
      
ads.ActivationArguments =
AppDomain.CurrentDomain.SetupInformation.ActivationArguments;
      
ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
       ads.PrivateBinPath = String.Concat(fCompilationFolder, ";", "Bin");
       workerAppDomain = AppDomain.CreateDomain(fAssemblyNameWithNoExt, AppDomain.CurrentDomain.Evidence, ads);
       ICodeExecution execCode = workerAppDomain.CreateInstanceAndUnwrap(fAssemblyNameWithNoExt, String.Concat(fDefaultNameSpace, ".", fClassNameToInvoke)) as ICodeExecution;
       execCode.DoExecute(ref executionParams);
}
finally
{
       AppDomain
.Unload(workerAppDomain);
}
Tabii ki bu sadece örnek bir kod. Yüklenen assembly içerisinde oluşacak herhangi bir hatanın uygulamamıza zarar vermemesi için try..catch bloğu ile korunması gerekmektedir.
Ali KALFAOĞLU

Yorumlar

Bu blogdaki popüler yayınlar

UML ve Modelleme – Bölüm 4 (Class (Sınıf) Diyagramları)

Bir önceki makalemizde UML modellemede kullanılan ilk diyagram olan Use Case diyagramını incelemiştik. Bu makalemizde nesne tabanlı programlamada kullanılan sınıflar ve sınıfların arasındaki ilişkileri modelleyebileceğimiz diyagramlar olan Class(Sınıf) diyagramlarını inceleyeceğiz. UML’de sınıflar, nesne tabanlı programlama mantığı ile tasarlanmıştır. Sınıf diyagramının amacı bir model içerisinde sınıfların tasvir edilmesidir. Nesne tabanlı uygulamada, sınıfların kendi özellikleri (üye değişkenler), işlevleri (üye fonksiyonlar) ve diğer sınıflarla ilişkileri bulunmaktadır. UML’de sınıf diyagramlarının genel gösterimi aşağıdaki gibidir. Şekil 1. Class Diyagram Şekil1’de görüldüğü üzere bir dikdörtgeni 3 parçaya bölüyoruz. En üst bölüm sınıf adını, orta kısım özellik listesini (üye değişkenler) ve en son kısım, işlev listesini (üye fonksiyonlar) göstermektedir. Çoğu diyagramlarda alt iki bölüm çıkarılır. Genelde tüm özellik ve işlevler gösterilmemektedir. Ama

Yazılım Maliyet Tahmineleme Tecrübeleri

Yazılım mühendisliğinde maliyet hesabı her zaman problem olmuştur. "Bu iş kaç Adam/Gün tutar?" sorusuyla sıkça karşılaşıyoruz. Adam/gün veya Adam/ay ölçütleri bir kaynağın/kişinin belirtilen zaman dilimindeki iş gücü anlamına gelir. Tabi bu noktada yine kafa karışıklıkları başlar. 6 A/G'lik bir işi hızlandıralım diye 2 kişi ile yapmaya çalışsak ve kaynak/kod, modül, altyapı, insan vb. her bir şeyi bir kenara bıraksak, matematiksel basit formülle 6/2=3 A/G'de biter? Gerçek hayat böyle değil, öncelikle bunu anlamamız lazım. Hep şu örnek verilir; "Aynı bebeği 2 kadın birlikte daha kısa sürede doğurur mu?" Eğer bunun cevabı "Evet" ise (veya bir gün böyle bir durum ortaya çıkarsa), yazımı değiştirmem gerekecek:) Mevzu gerçekten derin...Maliyet hesabı; bulunduğunuz firmanın yazılım süreçlerini hangi methodlarla uyguladığına, ilgili işin o dönemdeki aciliyetine, (şirket yönetiminin baskısına:)) vb. bir çok duruma bağlı olabilir. Örneğin; bizim firmada e

UML ve Modelleme – Bölüm 3 (Use Case Diyagramlar)

Önceki iki makalemizde ( 1 , 2 ) UML’e genel olarak değinip ve modellemede kullanacağımız dokuz diyagram hakkında bilgiler vermiştik. Bu makalemizde Use Case diyagramından detaylı bahsedeceğiz. Öncelikle, genel Use case diyagramının tanımını hatırlayalım. “Bir kullanıcı ve bir sistem arasındaki etkileşimi anlatan senaryo topluluğudur.” Ivar Jacobson Senaryo tanımı için der ki: “Aktörle sistem arasında gerçekleştirilen, sonucunda aktöre farkedilir getirisi/ faydası oluşan etkileşimli diyalogdur. ” UML Use Case Diyagramları  sistemin işlevselliğini açıklamak amacıyla kullanılır. Sistemin birbirinden ayrı özelliklerinin detaylarını göstermekten ziyade, Use Case Diyagramlar, tüm mevcut işlevselliği göstermek için kullanılabilir. Buradaki en önemli noktalardan biri,   Use Case Diyagramlar temelde sequence diyagram ve akış diyagramlarından farklıdır. Use Case diyagramlar dört ana elemandan oluşmaktadır. Aktörler , Sistem (Proje kapsamını belirtir) , Use Caseler ve bunlar ara