Erhan Ballıeker

NetStandard nedir? .NetCore, .NetFramework ve diğer .Net Platformları ile ilişkisi nasıl? (Bölüm 2)

Selamlar, bir önceki yazımda anlatmaya başladığım .NetStandard hakkında bilgiler vermeye devam edeceğim bu yazımdan önce, eğer okumadıysanız 1.Bölüm‘ü okumanızda fayda var.

Önceki yazıyı, buradaki kaynaktan aldığım resimle bir özetleyelim 🙂

standarddiagram

Resimde de görüldüğü gibi .NetStandard, birbirinden farklı .Net platformlarında ortak kod paylaşımı yazmayı kolaylaştırmak için tüm platformların uyması gereken bir standard getirerek .Net Platformlarını birleştirmek ve ileride farklı platformların da doğmasıyla çıkabilecek başka sorunlara da çözüm olmak amacı ile ortaya çıktı.

Bu yazımıza biraz daha soru cevap şeklinde devam edeceğim. Farklı sorularınız olursa yorum yazmaktan çekinmeyiniz.

Kütüphane yazarken hangi .NetStandard versiyonunu seçmeliyim?

Aslında bu sorunun cevabı çok net. .NetStandard yerine geçtiği PCL aksine lineer olarak versiyonlanıyor. Yani daha yüksek versiyon demek daha fazla ortak API kullanımı, ve eski .NetStandard versiyonlarına destek demek. Bu yüzden yeni oluşturacağınız Class Library leriniz için bügünden itibaren .NetStandard 2.0 seçmeniz en mantıklısı olacaktır.

Bununla beraber şunu da söylemekte fayda var, .NetStandard versiyonları immutable olarak sunuluyor. Yani bir versiyon release olduğunda ona artık dokunulmuyor. Yeni bir versiyonda olması planlanan API lar önce platform spesifik ortamlarda implemente ediliyor (örneğin .NET Core). Eğer ekip bu API ın tüm platformarda olması gerektiğine karar verirse yeni .NetStandard versiyonuna bu API ekleniyor. Yani geçmişle uyumsuzluk yok, ve hangi API ların .NetStandard a ekleneceği çok dikkatlice seçiliyor.

Peki bu .NetStandard da neler olacağına kimler karar veriyor?

Hemen akla gelen ilk isim doğru tabii, Microsoft 🙂  Önemli .Net Plarformlarının(NET Framework, .NET Core, ve Mono) implemente eden firma olarak Microsoft başta olmak üzere, Unity asıl rol oynuyır diyebiliriz. Eğer isterseniz sizlerde buradan bu sürece katılabilir, fikirlerinizi söyleyebilirsiniz. Belki önereceğiniz bir API bir sonraki versiyonda hayatımıza girecektir =)

.NetStandard 2.0 ile gelen .NET Framework Uyumluluk modu nedir?

Bu uyumluluk modu sayesinde bir .NetStandard class library projenize, .NetFramework library sini, sanki .NetStandard 2.0 için derlenmiş gibi ekleyebilirsiniz. Fakat tahmin edeceğiniz üzere her API çalışmayacaktır. Örneğin, WPF için yazılmış bir API ı, .NetStandard projenize elediğinizde, onu Xamarin vs için kullanamayacaksınız. Peki bu şekilde çalışması kesin olmayan bir API eklediğinizi nasıl anlayacaksınız?

rest

bu itici ünlem işareti ve uyarısı tanıdık geldi mi? 🙂 İşte bu uyarı Visual Studio size şunu söylüyor;

  • Ben istediğin paketi, sanki NetStandard için derlenmiş gibi projeye eklemeye çalıştım fakat, bu pkaetteki her API buna uyumlu değil. Bu yüzden bunu en uyumlu kullanabileceğin versiyon ile restore ettim. Eğer sorun yaşamazsan ne ala, yaşarsan günah benden gitti 🙂

diyor. Eğer gerçekten sorun yaşamaz, eklediğiniz API ın düzgün çalıştığını görürseniz. bu mesajı her derlemede görmemek için şunu yapabilirsiniz. Proje dosyasını açarak aşağıdaki gibi ilgili paketin ve versiyonunun adını yazarak bu uyarıdan kurtulabilirsiniz.

<ItemGroup> <PackageReference Include="XXX" Version="XXX" NoWarn="NU1701" /> </ItemGroup>

 Ben tam olarak neden PCL yerine .NetStandard kullanayım anlamadım

Diyecek olanınız var ise şöyle diyeyim;

Evet ikisininde nihai amacı aynı, ortak binary kod paylaşımı sağlamak. Ama arada ciddi farkları var.

  1. .NetStandard a eklenecek API lar özenle seçilip, önce platform spesifik taraflarda implemente edilip sonrada tüm platformlarda olup lmadığına karar veriliyor. PCL ise sadece farklı platformlar için kullanılan BCL lerdeki ortak API ları alıyor. Bir nevi sadece kesişim kümesini alıp çekiliyor aradan.
  2. .NetStandard da emin olabilirsiniz ki, yeni bir versiyon ile geride kalan tüm versiyonları desteklersiniz. Lineer bir versiyonlama vardır. Ama PCL bu şekilde çalışmıyor.
  3. Belkide en önemli fark şu ki; PCL Microsoft bağımlı iken, .NetStandard platform-agnostic. Hatta bir adım ötesi, Microsoft a özel olmamakla beraber .NetStandard aynı zamanda C# bağımsız. Herhangi bir language-spesific api bulunmuyor ve eklenmesi de düşünülmüyr henüz. Aslında zaten doğasında bu var, böyle olmak zorunda çünkü artık .Net platformları hemen hemen her yerde çalışıyor =)

.NetStandard ile destekleyebileceğim maksimum .Net Framework versiyonu nedir?

Şu an için 2.0 ile beraber Framework 4.6.1 i full kullanabiliyor olucaksınız.

.NetStandard a eklenecek API lara nasıl karar veriliyor?

Bunun için öncelikle Hem .NetFramework tarafında hem de Xamarin tarafında çalışan API lar göz önünde bulunduruluyor. Bu aşamadan sonra API ları required veya optional  ikiye ayırıyorlar. Required olanlar tamamen implemente edilmeye çalışılırken optional olanlar ayrı nuget paketleri halinde .NetStandard için uyumlu olucak şekilde derlenmeye çalışılıyor. Fakat nuget paketi olarak gelen her API ın her fonksiyonunun çalışma garantisi yok daha önce belirttiğim gibi.

Peki Platform spesifik API ların ne olacağına nasıl karar veriyorlar?

Tüm platformlarda çalışacak API lar yazmaya çalışılırlen karşılaşılan en büyük sorunlardan biri de, Platform spesifik API lar ile ilgili nasıl ilerleneceği. Bu tür API lara örnek olarak;

  • Runtime Spesific API lar
  • Operating System Spesific  API lar

Runtime spesifikler için reflection ile, runtime da kod oluşturup çalıştırmayı düşünebiliriz. Ama iOS buna izin vermiyor mesela, yada JIT compiler a sahip olmayan Windows platformları da bunu yapamayacak. Windows Registry de OS Spesifik olarak düşünebiliriz.

Peki siz olsanız bu durumda nasıl karar verirdiniz? Olasılıkları düşünelim

  1. İlgili API ı direk Unavailable yapmak
  2. .NetStandard a yine de eklemek ama desteklenmeyen platformlarda hata fırlatmak
  3. API simüle etmek 🙂

3. maddeye örnek olarak şunu söylebiliriz. Mono Registry API implementasyonu .ini dosyaları üzerinden yapıyor. Bu sayede uygulama kendi state i ile ilgili bilgileri registry de saklayabiliyor, fakat kendi dışında, mesela işletim sistemi ile ilgili bilgileri oradan okuyamıyor.

.NetStandard ekibi de sizin gibi düşünmüş olacak ki, hepsinin karışımı bir yol izlemek istiyorlar 🙂 Öncelikle .NetStandard’a sadece her platformda çalışacak API ları ekliyorlar, sonrasında popüler olanları ayrı nuget paketleri halinde .NetStandard ın üzerinde oturacak şekilde nuget e koyuyorlar(Tekrar belirtelim her fonksiyon çalışmayabilir). Bu kendi halinde ayrıştırılabilen ve kendi kendine yeten paketler için güzel çalışan bir yöntem. Fakat API ın tamamı bu şekilde değilse, 2. yada 3. yolu izliyorlar.

Peki gelelim esas sorulardan birine 🙂

.NetCore ile .NetStandard arasındaki bağ nedir?

.NetCore diğer .Net Platformlarına kıyasla en az API sayısına sahip ve en yavaş, dikkatli geliştirilmesi gereken bir framework. Sebebi belli, NetStandard ın tüm .Net Platformalarında çalışması istendiği gibi, .Net Core un da, neredeyse tüm OS, ve mimari seviyelerde çalışabilmesi isteniyor. Ortaya çıkış amacı bu zaten. Windows/IIS vs. bağımlılığın ortadan kalktığı her ortamda çalışabilen bir ürün olması. Ama runtime, OS level vb farklılıklar için ortak kod yazmak .NetStandard ın geliştirilmesi gibi hızlı gitmiyor. .NetStandard ın her bir versiyonunun immutable olduğundan söz etmiştik. Ve nasıl API ların seçildiği. Her bir platform kendine özgü API ları eklerken bir yandan da hangilerinin universal olabileceklerine karar veriyorlardı.

En nihayetinde durum .NetCore ve .NetStandard ı ayırmakla son buldu, çünkü tüm .net Platformlarında çalışacak olan API ları .NetCore tarafına ekleyip tüm işletim sistemi ve mimarilerde çalıştırmak mümkün olmuyordu.

Bu yüzden de .NetCore tarafından diğer platformlarda bulunan uyumluluk modunu kaldırdılar.

Artık NetCore bağımsız bir şekilde daha hızlı ilerliyor, ve yine gün sonunda core dahil olmak üzere ortak olması gerektiğini düşündükleri API ları, yeni .NetStandard versiyonlarına ekliyorlar.

.NetCore 2.0 tümüyle .NetStandard 2.0 uyumlu olduğundan, korkacak birşey aslında yok 🙂 Ama bu noktaya gelene  kadar ki sürece bilmek te fayda olduğunuz düşünüyorum

Bir sonraki yazımda görüşmek üzere..

 

.NetStandard nedir? .NetCore, .NetFramework ve diğer .Net Platformları ile ilişkisi nasıl? (Bölüm 1)

Selamlar arkadaşlar. Bu yazımda .NetStandard ın ne olduğunu, çıkış amacını, .Net platformları arasında ne tür bir öneme sahip olduğunu anlatıp, birçok kişiden duyduğum “Ya şimdi bu .netcore çıktı, netstandard geldi, zaten netframework vardı, ne oluyor arkadaş, ben neyi nasıl kullanacağım?” şeklindeki kafa karışıklıklarını tamamen gidermeye çalışacağım. Ayrıca farklı .Net platformları arasındaki kod paylaşım tekniklerine değinip, .NetStandard’ın PCL(Portable Class Library)’den farkına da değineceğim.

Öncelikle şuradan başlayalım, farklı .NET platformları derken nelerden bahsediyoruz?

  • .NET Core
  • .NET Framework
  • Mono
  • Xamarin.iOS
  • Xamarin.Android
  • Xamarin.Mac
  • Universal Windows Platform
  • Windows
  • Windows Phone
  • Windows Phone Silverlight
  • Unity

Evet aslında yukarıda ki listeye baktığımıza, artık bir kişinin “Ben .net developer’ım”  demesiyle birlikte aslında ne kadar geniş çapta işler çıkartabileceğini görebiliriz 🙂 Birbirinden farklı ve güzel birçok platform mevcut. Oyun geliştirmek, iOS, Android ve WP ye native mobil uygulamalar yazmak,  Web uygulamaları geliştirmek, Windows, Xbox, Console vs bir çok ihtiyaç için birçok uygulamayı .Net kullanarak geliştirebiliyoruz. Fakat bu yelpaze genişledikçe, Visual Studio daki Solution’lar büyüdükçe, Client’ların arayüz istekleri değiştikçe, ortaya çıkan en büyük soru şu oluyor

–  Ben tüm projemde ortak olması gereken kodları nasıl paylaştıracağım?

Ortak olması gereken kodlar nelerdir biraz düşünelim;

  • Application Services katmanı olabilir. Uygulamanın tüm business ihtiyacını yazacağımız katmanı ortak kullanılacak şekilde bir kere yazmak mantıklı olabilir.
  • Ortak bir Data Acces Katmanı olabilir. Repository, UnitOfWork vs gibi pattern ler ile ihtiyacımıza göre düzenleyip yazdığımız, belki bir ORM (EntityFramework, NHibernate) veya mikro ORM (Dapper vs.) kullandığımız, ortak bir data access katmanı mantıklı olabilir.
  • Ortak bir Networking Layer olabilir. Uygulamalarımız dış dünya ile haberleşirken, API’lar ile yapacakları haberleşmeleri ayrı ayrı yazmak istemeyiz. Tek bir yerde, kurallara uygun, düşünülmüş bir katman yazmak çok daha faydalı olacaktır.
  • DTO (Data Transfer Object) – POCO (Plain Old CLR Objects) lar ortak bir yerde olabilir. Evet spesifik projeler içerisinde model şekilleri değişip, client’a özel modeller oluşturmak gerekebilir. Ama en nihayetinde DB’den çıkan entity leri Data Access den bir üst level a taşımamak mantıklı olucaktır. Bu yüzden ortak bir dto katmanı mantıklı olabilir.
  • Bunların dışında Cross-Cutting-Concerns denilen, tüm uygulamalarda kullanılacak olan, Log, Security, Cache vb. gibi fonksiyonaliteleri bir abstraction olarak ortak bir yerde yazmak mantıklı olabilir.

Peki, evet bunları tek bir yerde yazalım ama, farklı .Net platformlarında bunları nasıl kullanacağım? Kullanabilir miyim?

Şüphesiz ki sorunun cevabı evet olmalı =) Bunu nasıl başaracağımıza bakalım. .NetStandard’tan önce bunu yapabilmek için 2 popüler yöntemimiz mevcut idi.

  • Shared Asset Projects (SAP)
  • Protable Class Library (PCL)

SAP: File linking gibi çalışan, Compiler Directive’ler kullanarak, platform spesifik kodlarınızı yazabileceğimiz bir teknikti. Örneğin

 
 #if __IOS__
  path = "iOS";
  #else

şeklinde SAP projesi içerisindeki bir .cs dosyasında, sadece Xamarin.iOS için çalışmasını istediğimiz bir kod yazabilirdik. Projeler derlendiğinde, SAP ayrı bir dll olarak değil, her bir referans olduğu projenin içerisine gömülmüş olarak hayatını sürdürürdü. Fakat bu yöntem tahmin edersiniz ki ortaya çok yönetilebilir olmayan ve karmaşık kodlardan oluşan projeler çıkartırdı.

PCL: SAP projeleri ile ilerlemenin pek yönetilebilir olmaması ve kod karmaşıklığına sebep olması yüzünden PCL kullanmak daha da mantıklı oluyordu. Fakat bu durumda da karşımıza farklı sıkıntılar çıkıyordu.

Şöyle düşünelim, bir solution var. İçerisinde her katman ayrı ayrı yazılmış güzelce. Fakat önyüz olarak, Silverlight, Xamarin.iOS, Web ve Desktop olması gerekiyor. Tüm bu farklı .Net platformları kendine has, kendine özel sınıfları ve fonskiyonaliteleri barındıran farklı Base Class Library (BCL)  ler kullanıyor. Peki bunların arasında ortak kümeyi nasıl bulacağız? Ya kulllandığımız özel bir sınıf, Web, Desktop ve Sliverlight ile uyumlu ama Xamarin.iOS ile uyumlu değilse ne olacak?

İşte bu problemlerle sonradan karşılaşıp kötü sürprizler yaşamamak için, .net ekibi şöyle bir çözüm getirdi.

  • Farklı  PCL Profiles 

Ne kadar farklı .Net platformları arasında kod paylaşmak istiyorsanız, kullanabileceğiniz ortak API sayısı da ters orantılı olarak düşüyordu. Yani sadece Web ve Desktop önyüzü ile proje geliştirirken neredeyse tüm .Net Framework üne ait sınıfları kullanabilirken, işin içine Silvelight, Xamarin, WP vs girmeye başladığında birçok sınıfı kullanamaz hale geliyordunuz. Örnek bir listeye bakalım

PCL Profile PCL Platforms
Profile7 .NET Framework 4.5, Windows 8
Profile31 Windows 8.1, Windows Phone Silverlight 8.1
Profile32 Windows 8.1, Windows Phone 8.1
Profile44 .NET Framework 4.5.1, Windows 8.1
Profile49 .NET Framework 4.5, Windows Phone Silverlight 8
Profile78 .NET Framework 4.5, Windows 8, Windows Phone Silverlight 8
Profile84 Windows Phone 8.1, Windows Phone Silverlight 8.1
Profile111 .NET Framework 4.5, Windows 8, Windows Phone 8.1
Profile151 .NET Framework 4.5.1, Windows 8.1, Windows Phone 8.1
Profile157 Windows 8.1, Windows Phone 8.1, Windows Phone Silverlight 8.1
Profile259 .NET Framework 4.5, Windows 8, Windows Phone 8.1, Windows Phone Silverlight 8

İşin içine Xamarin, UWP vs girmeye başladıkça çarşı hepten karışmaya başlıyor, API sayısı iyice azalıyor, tüm projelerinizde kullandığınız popüler bir nuget paketini bile ortak projelerinize ekleyemez oluyordunuz, çünkü ilgili PCLProfile ında çalışmayabiliyordu.

Peki ne olacak? Belli ki bu kod paylaşım işine daha kalıcı bir çözüm lazım. Aslında gerekli olan, farklı .Net platformlarının uyması gereken bir standard olması lazım 🙂

Bunun da farkına varan Microsoft .NetStandard ı hayatımıza kattı.

Nedir Bu .NetStandard?

Aslında işin derinine inmeden, .NetStandard ı  ve 2.0 ile ilgili bazı özellikleri özetleyerek bu bölümü sonlandıralım.

  • .NetStandard’ı tüm .Net platformlarının bundan böyle implemente etmek zorunda olduğu bir Interface gibi düşünebiliriz.
  • Birçok API ı içerisinde barındıran, tüm platformların da bunları implement etmek zorunluluğu sayesinde, farklı .Net platformlarını birleştiren ve gelecekteki ayrışmaları önleyecek bir Unified BCL olarak düşünebiliriz 🙂 2.0 ile beraber ortak API sayısı 32.000 i geçti ve bir önceki versiyona oranla(1.6) %142 büyüdü. Bu çok ciddi bir oran. Aşağıda bazı Temel API ları listeliyorum.
    • Xml (Xlinq, XmlDocument, Xsd, Xsl, Xpath)
    • Serialization (DataContract, Binary Formatter, XML)
    • Networking (Http, Sockets, WebSockets, Mail)
    • IO (Files, Compression, MMF)
    • Threading (Thread, ThreadPool, Task)
    • Core (Primitives, Collections, Linq, Interop, Reflection)
  • .NetStandard 2.0 ile beraber gelen bir uyum sağlama katmanı sayesinde, netstandard kütüphanelerinizden  sayısı her geçen gün artan .NET Framework binary leri referance alabileceksiniz, Ve Tabii ki, önceki tüm .NetStandard versiyonlarına ait API larıda kullanabileceksiniz.
  • .NetStandard artık gelecekte PCL in yerini alacak, bu yüzden şuandan itibaren yeni projelerinizin tümünde kod paylaşımı olarak, .Netstandard ı tercih edebilirsiniz.

Hazır PCL projelerinden bahsetmişken ve .NetStandard ın gelecekte PCL in yerini alacağını söylemişken, yukarıdaki PCL Profile tablomuza birde Profile ların uyumlu olduğu .NetStandard versiyonlarını ekleyip gösterelim. Bu profile lar ile mevcut proje geliştirenler, PCL yerine ilgili .NetStandard kütüphanelerine geçekten çekinmesinler =)

PCL Profile .NET Standard PCL Platforms
Profile7 1.1 .NET Framework 4.5, Windows 8
Profile31 1.0 Windows 8.1, Windows Phone Silverlight 8.1
Profile32 1.2 Windows 8.1, Windows Phone 8.1
Profile44 1.2 .NET Framework 4.5.1, Windows 8.1
Profile49 1.0 .NET Framework 4.5, Windows Phone Silverlight 8
Profile78 1.0 .NET Framework 4.5, Windows 8, Windows Phone Silverlight 8
Profile84 1.0 Windows Phone 8.1, Windows Phone Silverlight 8.1
Profile111 1.1 .NET Framework 4.5, Windows 8, Windows Phone 8.1
Profile151 1.2 .NET Framework 4.5.1, Windows 8.1, Windows Phone 8.1
Profile157 1.0 Windows 8.1, Windows Phone 8.1, Windows Phone Silverlight 8.1
Profile259 1.0 .NET Framework 4.5, Windows 8, Windows Phone 8.1, Windows Phone Silverlight 8

Bu bölümü burada sonlandıralım. Bir sonraki bölüm de .NetStandard da ile ilgili yazmaya devam edeceğim. İşin biraz daha otaya çıkışını, biraz daha derinini öğrenmek isterseniz, bir sonraki yazımda görüşek üzere 🙂

 

Yardımcı kaynaklar:

https://github.com/dotnet/standard/blob/master/docs/faq.md

https://docs.microsoft.com/en-us/dotnet/standard/net-standard

https://blogs.msdn.microsoft.com/dotnet/2016/09/26/introducing-net-standard/

https://docs.microsoft.com/en-us/dotnet/api/?view=netstandard-2.0

 

UrhoSharp ve Xamarin Workbook

Herkese Merhaba,

Bir önceki yazımızda Urhosharp’ın ne olduğundan ve bu kütüphaneyi kullanmak için bilmemiz gereken temel terimlerden bahsetmiştik. Bu yazımızda da bu terimleri kullanarak, Xamarin Workbook ile bir kaç örnek yapacağız. Örnekleri Workbook ile yapmayı seçmemin sebebi, hem Xamarin Workbook u biraz tanıtmak ve ne kadar kullanışlı olduğunu göstermek, hem de kod tarafında yaptığımız en küçük değişiklikleri anında görmek, telefona deploy etmenin verdiği zaman kaybından kurtulmak.

Tamamen ücretsiz ve çok kullanışlı olan Xamarin Workbook’u hem windows hem de  Mac için buradan indirebilirsiniz. Örnekleri inceleyebilir ve geri bildirimlerde bulunabilirsiniz.

workbook

Xamarin Workbook’u bilgisayarımıza indirip kurduğumuzda yandaki şekilde gördüğümüz gibi bir ikonla karşımıza çıkıyor.Bu ikona tıklayarak Workbook u açıyoruz.

workbooktemp

Workbook u ilk açtığımızda karşımıza bir template seçim ekranı geliyor. Burada Android, iOS, WPF, Console (.Net Framework veya .Net Core )seçimi yaparak workbook u hazırlıyoruz. Ben bu örneğimizde Console (.Net Framework) seçerek ilerliyeceğim.

Artık seçimlerimizi yapıp boş bir Workbook açmış olduk. Bu ekranda yapabileceklerimizden biraz bahsedip, örneğe giriş yapacağım.

workbookfile

Sol tarafta, workbook’u oluşturduğumuz ismin altında iki adet tab mevcut. Biri NuGet packages, diğeri kodlarımızı ve notlarımızı yazacağımız workbook’umuz. Tıpkı Visual Studio dan alışık olduğumuz gibi istediğimiz Nuget Package ı projemize ekleyip, projemizde kullanabiliyoruz. Hemen orta bölümde ise, workbook’umuzun kendisi mevcut, boş bir Executable cell ile gelmiş halde duruyor.  Workbook’a iki farklı satır(cell) ekleyebiliriz. Bunlardan biri Executable C# Cell bir diğeri de Documentation Cell. Her bir hücrenin en alt sağ tarafında, 3 buton mevcut. Bu butonları kullanarak, ilgili hücreyi silebilir, yeni bir dökümantasyon yada C# executable cell ekleyebiliriz. eklediğimiz hücre eğer çalıştırılabilir C# hücresi ise, hemen sol alt tarafında bir play butonu görüyor olacağız. Bu  butona bastığımızda, o hücre çalışacak ve bize o blokta ki çıktıyı (genellikle aynı hücre içerisinde en son satırda yazdığımız kodun çıktısı) hemen hücrenin altında bize gösterecek.

Workbook ile çalışırken dikkat etmemiz gereken önemli bir konu var. yukarıda bahsettiğim gibi, her bir executable cell çalıştığında, çıktıyı bize alt tarafında gösterecek, yani her bir hücrenin geriye birşey dönmesi gerekli. Normalde, Visual Studio kullanarak bir UrhoSharp örneği yapmaya kalkışsak, kendi Application objemizi, Urho.Application sınıfında türetip, gerisini bu application sınıfına bırakırdık. Bu miras aldığımız Application objesi, bizim kendi application objemiz içerisindeki “Run” methodunu tetikleyip, uygulamamızı başlatır, ve biz bir şekilde uygulamayı kapatmadığımız sürece de durdurmazdı. “Run” methodu da blocker bir method olduğundan, Workbook’ta kullanıma uygun değil malesef. Ama tam olarak bu workbook’ta kullanımımıza sunulmuş bir nesne var. SimpleApplication nesnesi bizim için, bazı initialization işlemlerinden sonra, bize bir application nesnesi dönüyor ve bunun üzerinden işlemlerimizi yapmaya devam edebiliyoruz.Bununla da kalmıyor, bizim için bir Camera, Light ve bir RootNode u üretmiş olarak kullanımımıza sunuyor.

Bir diğer dikkat etmemiz gereken konu ise, Workbook içerisindeki her bir executable cell tekrar tekrar çalışabilir olduğundan, uygulamamızda yapacağımız bazı işlemlerin, öncesinde tersini yapmamız gerekecek. Örneğin, Scene’imize bir node eklemeden önce o node u sileceğiz, veya bir event tanımladığımızda onun öncesinde de biraz reflection kullanıp kaldırmamız gerkecek. Bu tarz küçük handikapların dışında, workbook ile çalışmaya başladığınızda, özellikle yeni bir şeyi öğrenme konusunda ne kadar işe yarar olduğunuz göreceksiniz.

urhopackage

Artık örneğimize geçebiliriz. Nuget Packages‘a sağ tıklayıp, “Add Pacakge…” butonuna basarak karşımıza gelen ekrandaki Search kısmına UrhoSharp yazıyoruz ve UrhoSharp1.5.22 paketini çift tıklayarak yada alt taraftaki Add Package butonuna basarak Workbook’umuza ekliyoruz.

Bu paketi projemize eklediğimizde, ilk executable cell imizde #r “Urho” şeklinde ilgili kütüphanenin referansının workbook a eklendiğini göreceğiz. Bir Executable daha açıp, workbook’ta kullanacağımız namespace’leri ekliyoruz. Bu örneğimizde sadece Urho namespace’i yeterli olacak. Ctrl + Enter ‘a basarak veya hücrenin altındaki play butonuna basarak ilgili hücreyi çalıştırabiliriz. Workbook bizim için yeni bir executable cell oluşturacaktır. kod yazarken bir sonraki satıra geçmek için Shift + Enter’a basabiliriz.

newapp

Namespace’imizi ekledikten sonra. Bahsettiğimiz SimpleApplication sınıfının static Show metodunu kullanarak kendimize, belirttiğimiz boyutlarda bir 3D canvas açıyoruz. bundan sonraki her işlemimizi bu canvas üzerinde göreceğiz. Static Show metodu bizden bir application options nesnesi bekliyor. Yeni ApplicationOptions oluşturup, canvasımıza istediğimiz width ve height ı verip canvas ı oluşturuyoruz.

Bu örneğimizdeki amacımız ekrana sadece basit bir çizgi çizmek =) Bunu yaparken bir önceki yazımızda bahsettiğimiz terimlerin nasıl kullanıldığını göreceğiz. Sonraki örneklerimiz daha komplike olacağından, bu terimleri kullanmaya alışmamızda fayda var.

Öncelikle, boş uzayda bir çizgi çizmek için ihtiyacım olan iki noktayı tanımlayacağım. Sonrasında bu noktaları VertexBuffer nesnesinde birleştirip, devamında Geometry, Model, Material, StaticModel, Component ve Node sınıflarını kullanarak, bu çizgimizi canvas’ta göstereceğiz.

VertexBuffer.PositionNormal[] vertices = {
    new VertexBuffer.PositionNormal{
        Position = new Vector3(0,0,0)
    },
    new VertexBuffer.PositionNormal{
        Position = new Vector3(2,0,0)
    }
};

Yukarıdaki şekilde bir Vertex dizisi oluşturduk. Hatırlayalım; Vertex oluştururken, bunu VertexBuffer sınıfında tanımlanmış public structure’ ları kullanarak yapıyoruz demiştik. Sadece Position özelliklerini tanımlayıp bir Vertices(birden çok vertex e verilen ad) oluşturdum. Bu Executable Cell i çalıştırdığımda, workbook bana hücrenin çıktısını yani iki elemanlı VertexBuffer.PositionNormal dizisini aşağıda gösteriyor.

outpar

Sırada VertexBuffer nesnemizi oluşturmak var.Aşağıdaki şekilde bir VertexBuffer objesi oluşturyorum. SetSize ve SetData metodları ile değerlerimi set ediyorum.

var vertexBuffer = new VertexBuffer(Application.CurrentContext, false){
    Shadowed = true
};
vertexBuffer.SetSize((uint)vertices.Length, ElementMask.Position | ElementMask.Normal, false);
vertexBuffer.SetData(vertices);

Şimdi bu vertexbuffer’ ın ne şekilde birleşeceklerini söyleyeceğim nesenemi yani Geometry’ imi tanımlıyorum.

var geometry = new Geometry();
geometry.SetVertexBuffer(0, vertexBuffer);
geometry.SetDrawRange(PrimitiveType.LineList, 0, 0, 0, (uint)vertices.Length, true);

Sırada Model sınıfımı tanımlamak var. oluşturduğumuz geometry nesnelerini Model nesnesi ile bir araya getirebiliyorduk. BoundingBox propertysine set ettiğimiz değerlerin bu örnek için bir önemi yok, o yüzden biri orijinde diğeri (1,1,1) noktalarında iki Vector3 tanımladım.

var model = new Model();
model.NumGeometries = 1;
model.SetGeometry(0, 0, geometry);
model.BoundingBox = new BoundingBox(new Vector3(0,0,0), new Vector3(1,1,1));

Oluşturmuş olduğum bu Model objemin görselliği ile alakalı değerleri Material nesnesi ile set ediyoruz. Bu örnekte basitçe, bir desen kullanmadan sadece bir mavi renkten oluşan Material oluşturuyorum.

var material = Material.FromColor(Color.Blue);

Sonunda ekranda göstermek istediğim modelimi oluşturmuş oldum. Bunu Simple Application’ın benim için oluşturduğu RootNode’a yeni bir node ekleyerek, ekranda gösterme kısmınıda yapıp, artık bu mavi çizgimi oluşturduğum canvas’ta görmek istiyorum. Workbook’ta her bir executable cell, tekrar tekrar çalışabileceği için, oluşturacağım node’u önce RootNode’dan kaldırıyorum ki duplicate node’larım olmasın.

app.RootNode.RemoveChild(app.RootNode.GetChild("lineNode"));
var lineNode = app.RootNode.CreateChild("lineNode");

var line = lineNode.CreateComponent();
line.Model = model;
line.SetMaterial(material);

Veee sonunda canvas’ımızda da şekilde ki gibi bir mavi çizgi görüyoruz. outputurho

Bir sonraki yazımızda, biraz daha kod ağırlıklı bir örnek yapacağız. O zamana kadar bu temel terimleri anlamakta ve en temel anlamda kullanmakta fayda olacaktır.

Bu örnekte yapmış olduğum workbook dosyasını şuradan indirebilirsiniz.

Bir sonraki yazıda görüşmek üzere…

UrhoSharp’a Giriş

Herkese Merhaba,

Bu yazımda 29 Eylül 2017 Cuma akşamı Yiğit Özaksüt  ve Cihan Yakar ile gerçekleştirdiğimiz Xamarin Istanbul Development Meetup etkinliğinde anlattığım UrhoSharp’tan bahsedeceğim.

Meetup’taki sunumumu şuradan indirebilirsiniz.

Şimdi UrhoSharp konusuna gelelim. UrhoSharp, Urho3D adıyla hayata geçmiş ve başarılı bir 3D grafik ve oyun motoru olan Cross-Platform çalışabilen ve C++ API’a sahip projenin, tam olarak Xamarin ve diğer Microsoft ortamlarında çalışabilecek C# / .NET wrappers ile yeniden yazılmış halidir.

urho1

3D konusuna daha önceden hiç bulaşmamış olanlar için öncelikle UrhoSharp’ı kullanırken fazlaca kullanacağımız birkaç  terimden bahsetmek istiyorum.

  • Vertex / Vertices
  • VertexBuffer
  • Geometry
  • Model
  • Material
  • StaticModel
  • Node
  • Light
  • Camera
  • Scene

Bunların neler olduğundan bahsedelim. Boş uzaydaki tek bir noktayı düşünün, bu noktayı UrhoSharp’ta tanımlamak için kullandığımız nesne Vertex ama kendisini tam olarak bu isim ile değil de VertexBuffer nesnesi içine tanımlanmış public structure’lar olarak göreceğiz. Birazdan detaya ineceğim ama öncesinde, boş uzaydaki bu noktanın (yani Vertex in) sahip olduğu özelliklerden bahsetmek istiyorum. Hepinizin tahmin edeceği üzere olmazsa olmaz ilk özellik bu Vertex‘in uzaydaki koordinatı (Position). Bu özelliği UrhoSharp içerisinde yine bolca kullanacak olduğumuz Vector3 nesnesi ile belirtiyoruz. Bu Vector3 nesnesi bizden x, y ve z koordinatlarını isteyen constructure’a sahiptir. Mesela basit bir Vector3 nesnesini şu şekilde tanımlayabilirsiniz:

var coordinate = new Vector3(0,0,0);

(Bu kod ile 3D uzayda, tam orijinde duran,  x, y ve z değerleri 0 olan bir Vector3 tanımlamış olduk)

Vertex‘ in önemli 3 diğer özelliği daha vardır:

  1. Normal: Vertex’in bulunduğu yüzeye dik olan vektördür. Bu özellik öncelikle bize ışık ile etkileşime girme konusunda çok fayda sağlayacak.
  2. Color: Vertex in sahip olacağı renk.
  3. Texture: Vertex in bulunduğu yüzeyi kaplayacak olan dokunun, bu vertex için olan 2 boyutlu koordinatıdır. Vector2 ile tanımlıyor olacağız.

Boş uzayda tanımadığımız bu noktaları, bir araya getirmek için kullanacağımız nesnemiz ise VertexBuffer olacaktır. Yukarıda söylediğim gibi Vertex UrhoSharp’ta programatik olarak birşeyler çizebilmemiz için gerekli olan en küçük parça ama onu bu isimle görmeyeceğiz demiştim. İşte ilgili özellikleri ile bu vertex’i, VertexBuffer altındaki public structure’lar ile şu şekilde tanımlayabilirsiniz:

var VertexBuffer.PositionNormal = new VertexBuffer.PositionNormal {…}

var VertexBuffer.PositionNormalColor = new VertexBuffer.PositionNormalColor {…}

var VertexBuffer.PositionNormalColorTextcoord = new VertexBuffer.PositionNormalColorTextcoord {…}

Position özelliği dışında, diğer özelliklerini boş geçerek bir Vertex tanımlaması yapabilirsiniz. Bir de çokça duyacağınız Vertices adından bahsedeyim. Bu aslında birden fazla Vertex için duyacağınız isimdir yani bir üçgen oluşturmak için 3 adet Vertex tanımladınız diyelim, bu arkadaşları hep beraber çağırmak için Vertices adını kullanacaksınız, bilginiz olsun.

Peki, devam edelim. Noktaları oluşturdunuz ve VertexBuffer içinde bunları topladınız, bu noktaların ne şekilde birleşeceklerini nasıl söylüyoruz?

Geometry: Bu sınıfı aynı ismiyle UrhoSharp’ta yine çokça kullanmanız gerekecek. Geometry, bir veya birden fazla VertexBuffer nesnesinin ne şekilde birleşeceklerini ve nasıl yorumlanacaklarını söylemek için kullanacağımız bir nesnedir.

Vertices hazır, VertexBuffer’lar hazır, Geometry ‘er hazır. Tüm bunlardan sonra bu Geometry nesnelerini bir araya getirip bir görsel tanımlama işine bizi yaklaştıran önemli sınıflardan biri ise Model sınıfı olacak. Model sınıfı ile bir veya birden çok geometry objesini bir araya getirip bir model yaratmış olacağız. Bunu projemize önceden tanımlanmış haliyle, “.mdl” uzantılı dosya olarak ekleyebiliriz ya da programatik olarak bunu başarabiliriz.

Material: Oluşturduğumuz bu model nesnesinin, 3 boyutlu görselliği ile alakalı bileşenlerini Material nesnesi ile tanımlıyoruz. İstersek sadece bir renk verebiliriz (ki bu durumda Vertex’i tanımlarken verdiğimiz Color değerlerini ezmiş oluruz, ama ezmemenin de yolları var tabii.) istersek de bir bitmap vb şekilde yüzeyi kaplayacak olduğumuz dokuyu verebiliriz.

Bu Model  ve Material nesnelerini biraraya getirip, nihai bir görsellik sağlamak için kullancağımız sınıf ise StaticModel component’i olacaktır. Hazır Component demişken, hemen ondan da kısaca bahsedelim. Component nesnesi ile artık hali hazırda olan modelimizi hayata geçirebiliyoruz. Hayata geçirmekten kastım, öylece duran modellerimize, eklediğimiz Component’ler sayesinde, ses yaymalarını, fizik kurallarından etkilenmelerini ve birbirleri ile etkileşime geçmeleri gibi birçok özelliği vermek.

Peki artık modellerimiz hazır, belli componentler ile belli özellikler de aldılar peki bunları ekranda nasıl gösteriyor olacağız?

Son 3 önemli terimden bahsetmek istiyorum,

  1. Camera: 3D ekranımızda Camera nesnesi kendi görüş alanında kalan herşeyi bize gösteriyor olacak. Camera objesininde tabii ki, uzayda bir Position‘ı ışık yayma şekli ve bir görüş alanı olacaktır. Bu görüş alanını FOV (Field Of View) dediğimiz özelliği ile belirteceğiz. (Default hali 45 derecedir.)
  2. Light: UrhoSharp’ ta 3 tip ışık var. Bu ışıkları sahnemizi aydınlatmak ve tüm objelerimizin ne şekilde görüneceğini belirlemek için kullanıyoruz. Tam burada şunu söylemek isterim ki 3D Grafikte Curve (eğri) yüzey diye bir tanım yoktur aslında. Eğim olarak gördüğümüz şey, ışığın geliş şekli ve o yüzeyi oluşturan Vertices’in Normal vektörleri ile yaptıkları açıların etkileşiminden başka bir şey değildir.
    1. Directional: Belli bir yönden gelen ve o doğrultuda ilerleyen sonsuz ışındır. Güneş ışını gibi düşünebilirsiniz.
    2. Point: Belli bir noktadan gelen ve tüm doğrultularda yayılan ışındır. Bir ampulün yaydığı ışın olarak düşünebilirsiniz.
    3. Spot: Belli bir noktadan gelen ve belli bir doğrultuda görülecek ışındır. El feneri gibi düşünebilirsiniz.
  3. Scene: Tüm modellerimiz ve kamera ile ışık sayesinde oluşturduğumuz sahneyi temsil etmektedir.

Bu kadar fazla terimden bahsettikten sonra örnek yapmadan olmayacaktır tabii ki. Bir sonraki yazımda, tüm anlattıklarımı içeren, güzel örnekler ile karşınızda olacağım. O zamana kadar, bu terimleri sindirmenizi, UrhoSharp ile ilgili bulduğunuz yazıları okumanızı öneririm. Birkaç yardımcı link vermek isterim:

  • Xamarin.com da buradaki linkten başlayarak ilgili tüm UrhoSharp yazılarını okumanızı öneririm. UrhoSharp’ı Xamarin.Forms ile kullanabileceğimiz gibi, tabii ki Xamarin.iOS yada Xamarin.Android ile de kullanabiliriz. Hatta Xamarin dışındaki diğer Microsoft yazılım platformalarında da rahatça kullanabilirsiniz. En nihayetinde başarılı bir  C++ API ile yazılmış kütüphanenin C# ve .NET wrapper ile devşirilmiş halini kullanıyorsunuz.
  • Bu temelleri anlamadan biraz sert kaçar ama, geçenlerde Charles Petzold abimizin yaptığı webiner ı izlemenin de ilerideki aşamalarda faydası olacaktır. Kendisi kod ile mobiusstrip yaptı, izlemeye kesinlikle değer.