Roslyn Scripting; Barındıran Uygulama ile Etkileşim

Script-File

   Hatırlarsanız Roslyn CTP’si ilk duyurulduğunda bu konuda bir grup makale yayınlamıştır. Bu makalelerden belki de en dikkat çekeni Roslyn sayesinde C#’ı bir script dili gibi nasıl kullanabileceğinizi paylaştığım Microsoft “Roslyn” CTP ile Scripting makalemdi. Geçen zamanla birlikte yayınlanan yeni CTP’lerle birlikte bu konuyu bir kez daha ele almanın faydalı olacağını düşündüm; ama bu defa farklı bir bakış açısı ile…

   Makaleye başlarken; öncelikle bir konsol uygulası oluşturup Package Manager Console üzerinden aşağıdaki komutla Roslyn.Compilers.CSharp NuGet paketini yükleyelim;

Install-Package Roslyn.Compilers.CSharp

  Roslyn ile script süreci öncelikle tüm süreci yönetecek script motorunun ilklendirilmesiyle başlar. Bu işlemi değişkenlerin durumlarının saklanacağı oturumun oluşturulması takip edecektir. Sonrasında iş mantığına göre kullanıcıdan alınan, bir dosyadan okunan ya da kod içerisinde oluşturulan dinamik kod çalıştırılacaktır.

   En basit haliyle bir Roslyn scipt oturumu aşağıdaki gibi olacaktır;

using System; 
using Roslyn.Scripting.CSharp;

namespace Enterprisecoding.RoslynScripting { 
    class Program { 
        static void Main(string[] args) { 
            var scriptMotoru= new ScriptEngine(); 
            var oturum= scriptMotoru.CreateSession(); 
            oturum.Execute(@"System.Console.WriteLine(""Merhaba Dünya"");");

            Console.ReadKey(); 
        } 
    } 
}

Uygulama çıktısı 

 

   Script işlemlerinin ana bileşenlerinden birisi olan oturumlar değişkenler kadar yeni oluşturulan fonksiyonları da saklamaktadırlar. Burada kadar her şey güzel; peki ya yazdığımız scriptler barındıran uygulama ile etkileşime geçmek isterlerse??

   Roslyn scripting, barındıran uygulama ile etkileşim için oturumu başlangıcında bir geçiş nesnesi kabul etmekte;

using System; 
using Roslyn.Scripting.CSharp;

namespace Enterprisecoding.RoslynScripting { 
    class Program { 
        static void Main(string[] args) { 
            var hostNesnesi = new HostNesnesi(); 
            
            var scriptMotoru = new ScriptEngine();

            var oturum = scriptMotoru.CreateSession(hostNesnesi); 
            oturum.AddReference(hostNesnesi.GetType().Assembly); 
            oturum.Execute(@"EkranaYaz(""Merhaba Dünya"");");

            Console.ReadKey(); 
        } 
    }

    public class HostNesnesi { 
        public void EkranaYaz(string metin) { 
            Console.WriteLine(metin); 
        } 
    } 
}

   Bu geçiş nesnesi, yukarıdaki örnekte olduğu gibi script ortamında bazı ortak işlerinizi toplayarak scriptinizi sadeleştirmenize yarayabileceği gibi aşağıdaki örnekte olduğu gibi veri alışverişinde de kullanılabilir;

using System; 
using Roslyn.Scripting.CSharp;

namespace Enterprisecoding.RoslynScripting { 
    class Program { 
        static void Main(string[] args) { 
            var hostNesnesi = new HostNesnesi(); 
            
            var scriptMotoru = new ScriptEngine();

            var oturum = scriptMotoru.CreateSession(hostNesnesi); 
            oturum.AddReference(hostNesnesi.GetType().Assembly);

            oturum.Execute(@"Metin = ""Merhaba Roslyn"";"); 
            oturum.Execute("EkranaYaz();");

            hostNesnesi.EkranaYaz();

            Console.ReadKey(); 
        } 
    }

    public class HostNesnesi { 
        public string Metin;

        public void EkranaYaz() { 
            Console.WriteLine(Metin); 
        } 
    } 
}

Roslyn-Cikti-2

 

   Şimdi.. Madem biz script oturumumuz ile barındırıcı uygulamamız arasında bir geçiş nesnesi ile bağlantı kurabiliyoruz; o zaman bunu bir adım daha ileri taşıyıp dinamikliğimizi arttıralım. Nasıl mı? Tabi ki delegete’leri kullanarak.

using System; 
using Roslyn.Scripting.CSharp;

namespace Enterprisecoding.RoslynScripting { 
    class Program { 
        static void Main(string[] args) { 
            var hostNesnesi = new HostNesnesi(); 
            
            var scriptMotoru = new ScriptEngine();

            var oturum = scriptMotoru.CreateSession(hostNesnesi); 
            oturum.AddReference(hostNesnesi.GetType().Assembly);

            oturum.Execute(@"Logla = mesaj => System.Console.WriteLine(mesaj)");

            hostNesnesi.Logla("Merhaba Roslyn");

            Console.ReadKey(); 
        } 
    }

    public class HostNesnesi { 
        public delegate void LoglamaDelegate(string mesaj);

        public LoglamaDelegate Logla; 
    } 
}

   Yukarıdaki kod parçacığını inceleyecek olursak HostNesnesi içerisinde doğrudan işlem yapan bir kodun yer almadığını görebiliriz. Bunun yerine bir delegate tanımı ve Logla delegate’i yer almakta. İşin güzel tarafı ise bu delegate’in işaret edeceği fonksiyonu dinamik olarak script oturumumuz içerisinde tanımlıyoruz. Sonrasında da barındıran uygulamamız içerisinde bu delegate’i çağırdığımızda dinamik tanımladığımız fonksiyon çalışmakta.

   Hatırlarsanız delegate’lerin multicast özelliği var. Dolayıyla da yukarıdaki örnek için; istersek farklı farklı oturumlarda oluşturacağımız loglama fonksiyonlarını aşağıdaki gibi tek seferde çağırmamız da mümkün;

using System; 
using Roslyn.Scripting.CSharp;

namespace Enterprisecoding.RoslynScripting { 
    class Program { 
        static void Main(string[] args) { 
            var hostNesnesi = new HostNesnesi(); 
            
            var scriptMotoru = new ScriptEngine();

            var oturum1 = scriptMotoru.CreateSession(hostNesnesi); 
            oturum1.AddReference(hostNesnesi.GetType().Assembly);

            oturum1.Execute(@"Logla += mesaj => System.Console.WriteLine(mesaj);");

            var oturum2 = scriptMotoru.CreateSession(hostNesnesi); 
            oturum2.AddReference(hostNesnesi.GetType().Assembly);

            oturum2.Execute(@"void RenkliLoglama(string mesaj) { 
                                System.Console.BackgroundColor = System.ConsoleColor.Blue; 
                                System.Console.ForegroundColor = System.ConsoleColor.White; 
                                System.Console.WriteLine(mesaj); 
                                System.Console.ResetColor(); 
                              }");

            oturum2.Execute(@"Logla += RenkliLoglama;");

            hostNesnesi.Logla("Merhaba Roslyn");

            Console.ReadKey(); 
        } 
    }

    public class HostNesnesi { 
        public delegate void LoglamaDelegate(string mesaj);

        public LoglamaDelegate Logla; 
    } 
}

Roslyn-Cikti-3

Fatih Boy

Ankara'da yaşayan Fatih, bir kamu kurumunda danışman olarak çalışmaktadır. ALM süreçleri, kurumsal altyapı ve yazılım geliştirme konularında destek vermektedir. Boş zamanlarında açık kaynak kodlu projeler geliştirmeyi ve bilgisini yazdığı makalelerle paylaşmayı seven Fatih, aynı zamanda Visual C# konusundan Microsoft tarafından dört yıl üst üste MVP (En Değerli Profesyonel) ödülüne layık görülmüştür. İş hayatı boyunca masaüstü uygulamaları, web teknolojileri, akıllı istemciler gibi konularda Asp.Net, Php, C#, Java programlama dilleri ve MySql, MsSql ve Oracle gibi veritabanı yönetim yazılımları ile çalışmıştır. İngilizce ve Türkçe olarak yayınlanan makalelerini gerek İngilizce bloğunda, gerekse de Türkçe bloğunda bulabileceğiniz gibi web sitesinden de açık kaynak kodlu geliştirdiği yazılımlarına ulaşabilirsiniz.
vCard - Twitter - Facebook - Google+

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir