Asp.Net Core Dışında Bir .NetStandard Kütüphanemizde (Ör: Xamarin.Forms Shared Projede) HttpClientFactory Kullanımı.
Selamlar,
Başlık konusunda biraz kararsız kalmıştım. Değinmek istediğim noktayı şöyle anlatayım. Asp.Net Core projesi dışında bir Client ınız olduğunu düşünelim (Console App, Xamarin Mobile App, WinForms, WPF, UWP vs vs..), bu projeden API call ları HttpClientFactory kullanarak nasıl yapacaksınız buna değinmek istiyorum.
Önceki yazılarımda Networking taraflarındaki konulara çokça değinmişimdir. Günümüzde de bir .net projesinde http üzerinden haberleşmek için artık elimizde en iyi sınıf HttpClientFactory gibi duruyor. Ama danışmanlıklarım sırasında şunu çok gördüm.
Asp.Net Core un genel olarak çalışma yapısı insanlarda oturmamış. Microsoft un tüm paketleri ayrı ayrı yapmasının sebebi çok anlaşılmamış. .NetStandard nedir, Core nedir, kafalarda karışıklıklar var.
Bunlar la ilgili konulara değindiğim yazılarıma bakmanızı tavsiye ederim.
- .NetStandard nedir? .NetCore, .NetFramework ve diğer .Net Platformları ile ilişkisi nasıl? (Bölüm 1)
- Xamarin.Forms’da Kod Paylaşımı İçin .NET Standard 2.0 Kullanımı
- Asp.Net Core da HttpClientFactory Kullanımı (Basic Usage)
İnernettki örneklerin birçoğu HttpClientFactory kullanımını bir Asp.Net Core projesi üzerinden anlatıyor. Asp.Net Core projesinde ki startup dosyasında IServiceCollection a httpclientfacory yi, named typed vs gibi farklı tiplerde istediğiniz gibi tanıtıp sonra da kullanıyorsunuz.
Ama bir xamarin projesi karşımıza çıktığında ve bu xamarin projesinden dışarıya yapacak olduğumuz requestleri HttpClient ile değilde HttpClientFactory ile olmasını istetdiklerinde, ortalıka ne bir Startup var, ne ServiceCollection vs vs.
Bu durumda yapıpyı kurmakta zorluk çekildiğini gördüm.
Önce şundan bahsedelim.
Asp.Net Core daki IServiceCollection ın Asp.Net Core projesine geldiği dll
Microsoft.Extensions.DependencyInjection paketi. Peki bu paketi ben başka bir .NetStandard kütüphaneme ekleyemez miyim? Evet ekleyebilirim.
.NetStandard ın ne olduğunu hatırlayalım kısaca;
- Microsoft un .netframework ünün birden fazla implementasyonu var. Yani bu framework ü bir Interface olarak düşünürseniz farklı implementasyonlardan kastım şunlar olucaktır;
- UWP
- WPF
- Asp.Net – Asp.Net Core
- Xamarin
- Mono
- vs..
- Tüm bu platformlar arasında kod paylaşımı için .netstandard a kadar iki farklı yönetmimiz var idi. Portable Class Library ler ve Shared Asset Project idi.
- Microsoft artık tüm platformlar arasında kod paylaşımını kolaylaştırmak için ortaya bir standard koydu. .NetStandard. Artık her implementasyon bu standard içerisindeki API ları kendine eklemek zorunda idi
- İlk başlarda çok fazla API içerisinde barındırmayan .NetStandard artık 2.0 versiyonu ile veraber tüm full .netframework 4.6.1 deki api lara bile sahip hale geldi. İçerisinde artık binlerce API var. Bu da şu demek, eğer nugetten indirdiğiniz bir kütüphane ya da sizin target olarak .NetStandard seçerek oluşturmuş olduğunuz bir kütüphane neredeyse üm .net implementasyonlarında çalışır olucak demek.
Peki bu özet bilgi ile şöyle bir işe kalkışalım. Bir solution ımız olsun. Bu solution içerisinde şunlar olsun.
- Bir Asp.Net Core ile yazılmış API
- Bir Asp.Net Core Web App (Client)
- Bir Xamarin iOS ve Android App (Client)
- Bir Console App (Client)
- Bir WPF App (Client)
Ve şunu istiyor olalım.
Tüm clienlar çoğunlukla olacağı gibi aynı Apı mız ile haberleşerek istediği işlemleri yapsın. Ve bu Api ile haberleşirken de HttpClient değil HttpClientFactory kullansın.
Hatta Eski yazılarımda olduğu gibi öyle bir Api Haberleşme sınıfı yazalım ki, buraya Refit, Polly gibi kütüphaneleri de kullanıp yine güzel bir Resilient Network Service altyapısı oluşturalım.
Tüm bunlaru yapmadan önce başlıkta dediğim gibi bir xamarin uygulamasında HttpClientFactory yi nasıl kullanırım bunu görelim.
Bunu yapmanın aslında ne kadar basit olduğunu görünce biraz şaşırabilirsiniz özellikle .Netstandard ve .Net Core ile beraber Microsoft un birçok paketi ayrı ayrı sunmasının faydalarını daha önce keşfetmediyseniz…
Bir xamarin uygulamasını neredeyse bir Asp.Net Core uygulaması gibi görünmesini sağlamak için yapmam gereken ilk şey 2 adet paketi .NetStandard kütüphaneme eklemek. Platforms spesifik projelerle şuan için işim yok. Boş bir xamarin.forms projesi açtıktan sonra (Empty template ile) ilk olarak aşağıdaki paketleri yüklüyorum nugetten.
bu iki paket şunlar;
- Microsoft.Extensions.DependencyInjection
- Microsoft.Extensions.Http
ilk paket ile uygulamama bir DI özelliği katıyorum, bunun içinde autofac, unity, ninject vs gibi bir IoC container kullanmadan Microsft un kendi extension paketi üzerinden yürüyorum. Bu noktada artık bir Asp.Net Core projesinde yaptığımız gibi her istediğimiz api ı bu container a ekleyip bunun üzerinden erişbilir olduk bile.
Diğer pakete de bana Asp.Net Core projesinde DI container a AddHttpClient dememi sağlayan ve HttpClientFactory devreye sokan extension metodun geldiği paket. Bu noktadan itibaren de artık bir core web app e eklediğim gibi ClientFactory yi ekleyebilirim.
Bunun için bir IServiceCollection field ını App.cs tarafında oluşturdum. Eğer null ise Constructor new ServiceCollection diyerek Container ı oluşturuyorum.
Daha sonrada uygulama sayfalarımdan burada register etmiş olduğum service lere ulaşmak için IServiceProvider property mi oluşturuyorum. Bunu ayağa kaldırmak içinde tüm serviceleri register ettikten sonra BuildServiceProvider() diyerek provider objemi oluşturuyorum. App.cs de yapacaklarım bu kadar.
public partial class App : Application { IServiceCollection services; internal static IServiceProvider ServiceProvider { get; private set; } public App() { InitializeComponent(); if (services == null) { services = new ServiceCollection(); } services.AddHttpClient(); ServiceProvider = services.BuildServiceProvider(); MainPage = new MainPage(); } .....
App.cs de gerekli işlemleri bir kaç satır da hallettikten sonra, ki bu birkaç satırda şunları yapmış olduk;
- Bir DI mekanizması oluşurup IoC container kurduk
- Bu Container a IHttpClientFactory yi register ettik
artık MainPage e geldiğimde, aşağıdaki gibi ServiceProvider üzerinden ilgili service ime ulaşabilirim. Burada ulaşmak istediğimiz service de IHttpClientFactory nin kendisi.
public partial class MainPage : ContentPage { IHttpClientFactory _clientFactory; public MainPage() { InitializeComponent(); _clientFactory = App.ServiceProvider.GetRequiredService<IHttpClientFactory>(); Task.Run(async () => { var result = await _clientFactory.CreateClient().GetStringAsync("http://randomuser.me/api?results=1"); }); } }
_clientFactory = App.ServiceProvider.GetRequiredService(); dedikten sonra artık bu clienFactory normal bir asp.net core projemdeki gibi elimde. Burada basic usage olarak kullandığımız için hiçbir parametre verdeden CreateClient diyerek HttpClient ımızı oluşturup gerekli işlemlerimizi bunun üzerinden yapabiliriz.
Görmüş olduğunuz gibi Microsoft un Asp.Net Core ile beraber kurmuş olduğu yapı oldukça esnek ve birbiri ile kullanılmaya oldukça müsait. Bir xamarin projemizde HttpClientFactory yi ve hatta Microsoft kendi micro Container ını kullanmış olduk.
Bir sonraki yazımda görüşmek üzere.

Xamarin.Forms’da Kod Paylaşımı İçin .NET Standard 2.0 Kullanımı
Herkese Merhaba,
Bu yazımda önceden oluşturduğumuz veya yeni oluşturacağımız Xamarin.Forms projemizde, PCL (Portable Class Library) yerine nasıl .Net Standart 2.0 kullanabileceğimizden bahsedeceğim.
Bildiğiniz üzere, Visual Studio ile sıfırdan bir Xamarin.Forms projesi oluşturulduğunda bize iki opsiyon sunar. Bunlardan biri PCL diğeri de Shared Project. Shared Project, aslında File Linking gibi çalışan yazdığınız kodların tüm projelerin içine ayrı ayrı kopyalandığı ve paketlendiği bir kod paylaşım şeklidir yani SP ayrı bir proje olarak derlenip size farklı bir dll sunmamaktadır. Küçük projelerde ve tek kişilik ekiplerle yapılan projelerde mantıklı gibi gözükse de proje ve ekip büyüdükçe sıkıntılar çıkarmaya başlar. Ayrıca aşağıdaki gibi Compiler Directive’ler kullanarak, platform spesifik kodlarınızı yazabilirsiniz. Bu ilk bakışta kolay ve kullanışlı gibi gözükmesine rağmen kodlar çoğaldığında, ortalık biraz karışacaktır ve kodun okunabilirliği düşecektir.
var path = string.Empty; #if WINDOWS_PHONE path = "windowsphone"; #else #if __SILVERLIGHT__ path = "silverlight"; #else #if __ANDROID__ path = "android"; #else #if __IOS__ path = "iOS"; #else #if __TVOS__ path = "tv"; #else #if __WATCHOS__ path = "watch"; #endif
Gerek Unit Test yazılabilirliği olsun, gerekse daha temiz bir kod paylaşımı sağlaması vb gibi farklı sebeplerden PCL birçok Xamarin projesinde kod paylaşımı stratejilerinin en başında gelmektedir.
Fakat bundan sonra, Xamarin.Forms 2.4.xx versiyonları ile beraber .NetStandard 2.0‘a tam destek gelmeye başladı. Microsoft’un da bundan sonra .NetCore‘a ve Standard Library ile yoluna devam edeceğini düşünürsek Xamarin projelerimizde kod paylaşımı için .NetStandard’a geçmenin vakti geldi.
NET Standard 2.0‘da şimdiden yazılımcıların hayatını kolaylaştırmak için 20000’den fazla API, en çok kullanılan nuget paketlerinin %70’inden fazlasına uyumluluk mevcut bile. Desteğe dahil olan platformlara UWP desteği ile beraber artık Xamarin de eklendi.
.NET Standard 2.0 kütüphanesini Xamarin.iOS 10.14, Xamarin.Android 7.5, Xamarin.Mac 3.8, and Mono 5.4 versiyonları ve sonrası ile kullanabilirsiniz.
Bilgisayarınızda .Net Core ilgili eksikleriniz varsa şuradan indirebilirsiniz.
Projemde Kullanacağım .NetStandard Versiyonunu Seçerken Neleri Düşünmeliyim?
- Ne kadar yüksek versiyon seçerseniz, o kadar çok API desteği alırsınız.
- Ne kadar düşük versiyon seçerseniz, o kadar çok platform tarafından implement edilmiş olan versiyonu kullanıyor olursunuz.
Aslında çok da fazla düşünmenize gerek yok çünkü .Net Standard 2.0 neredeyse tüm platformlar tarafından destekleniyor.
- NET Core 2.0
- .NET Framework 4.6.1
- Mono
- Xamarin.iOS
- Xamarin.Android
- Xamarin.Mac
- UWP
Tüm bu platformlar hali hazırda Net Standard 2.0′ı implement etmiş durumda.
Peki projemizdeki kod paylaşımını .Net Standard 2.0 olacak şekilde değiştirmekten bahsedeyim. Sıfırdan bir proje oluşturarak işe başlayacağım. Henüz kod paylaşımı için ilk başta Visual Studio bize seçenek olarak .Net Standard 2.0 sunmadığı için PCL seçimi yapacağım ve akabinde bunu .Net Standard 2.0 olarak değiştireceğim.
Yukarıdaki seçeneklerle sıfırdan bir Xamarin.Forms projesi oluşturuyorum ve bana yandaki gibi bir Solution veriyor (Windows seçeneği için “İptal” tuşuna bastım. Şu an için onunla ilgilenmiyorum).
Projede hiçbir değişiklik yapmadan önce, solution’ı derliyorum. Tüm solution’ın sorunsuz derlendiğine emin olduktan sonra Solution’a sağ tıklayıp Add New Project diyorum.
Aşağıdaki gibi sol taraftaki menüden .Net Standard’ ı seçiyorum ve isimde hiçbir değişiklik yapmadan ClassLibrary1 olarak projemi solution’ a ekliyorum.
Solution’a eklediğim bu SCL’min versiyonu default olarak (Eğer pc’nizde yüklü ise) 2.0 olarak gelmektedir. ClassLibrary1 projesine sağ tıklandığında en altta Properties’e tıklarsam karşıma gelen pencerenin Target framework kısmında SCL versyionunu görüp bu versiyonda değişiklik yapabilirim.
Şimdi ClassLibrary1 projemde Dependencies’e sağ tıklayıp Manage Nuget Packages.. ‘a tıklayıp Xamarin.Forms kütüphanesini ekleyeceğim.
Yukarıda gördüğünüz gibi, ClassLibrary1 projeme Xamarin.Forms 2.4.0.282 (bu yazıyı yazarken ki son stabil versiyon) kütüphanesini ekleyip derliyorum. Projenin derlendiğine emin olduktan sonra, Pcl projesindeki App.xaml ve MainPage.xaml dosyalarını CTRL tuşuna basarak seçiyorum ve mouse yardımı ile iki dosyayı SCL projeme sürükleyip bırakıyorum (yani kopyalamış oluyorum). Bunu yaptıktan sonra artık PCL projemi solution’dan silebilirim. PCL projesini silmeden önce eğer projenizde daha fazla dosya varsa tüm dosyaları SCL’e kopyaladığınıza emin olun mutlaka.
ClassLibrary1 olarak eklediğim SCL’nin adını, bu proje mouse ile seçili iken F2 tuşuna basarak, App1 olarak değiştiriyorum (ilk oluşturduğumda projeme verilen default isim bu olduğu için App1 yaptım. Eğer sizin önceden oluşturduğunuz bir projeniz varsa ve PCL in adı örneğin MyApp ise SCL’e de App1 değil bu MyApp ismini veriniz.).
Solution’ımın son hali yandaki gibidir. Gördüğünüz gibi App1 projesi artık bir .NetStandart2.0 projesidir. Dependencies altındaki Xamarin.Forms paketinin yanında sanki sorunluymuş gibi bir ünlem işareti var ama bunu şimdilik dikkate almayın. Projede sorun olmamasına rağmen Visual Studio bunu şimdilik yapıyor ancak Visual Studio’yu açıp kapattığınızda sorun düzeliyor. Fonksiyonel olarak bir sıkıntı olmadığına emin olmak için SCL projemizi derliyoruz. Projenin derlendiğine emin olduktan sonra Android ve iOS projeme bu App1 projemin referansını ekliyorum.
İlk başta gelen App1 ismindeki Portable Class Library projemi Solution’dan sildiğimde, referanslar Android ve iOS projesinde kalkmış oldu. Bu yüzden bu yeni oluşturduğum SCL kütüphanemin referansını, iOS ve Android projeme tekrar ekliyorum. Şimdi yeniden Android ve iOS projelerimi derlediğimde sorunsuz derlendiğini görüyorum. Bu noktadan itibaren Xamarin.Forms projeme .NetStandard 2.0 ile devam edebilirim.
Bu yazımda kısaca, var olan veya yeni oluşturduğum bir Xamarin.Forms projemin kod paylaşım stratejisi olarak nasıl PCL’den .NetStandard’a geçebileceğimizi anlatmaya çalıştım.
Özetlemek gerekirse:
- Solution’a yeni bir .NetStandard 2.0 ClassLibrary’si ekliyorum.
- Bu yeni eklediğim SCL’e Xamarin.Forms nuget Package’ını ekliyorum.
- Önceden oluşan PCL’deki dosyaları (xaml, .cs vs) bu yeni oluşturduğum SCL içerisine taşıyorum.
- PCL projesini solution’dan kaldırıyorum.
- SCL’in ismini projeden kaldırdığım PCL’in ismi olacak şekilde değiştiriyorum.
- Son olarak bu yeni oluşturduğum SCL’in referansını Android ve iOS projelerime ekliyorum.
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 3)
Selamlar, .NetStandard ile ilgili örnek yapıp bir de developer gözünden bir metafor ile netstandard a bakıp bu seriyi sonlandıracağım yazıma hoşgeldiniz. Önceki yazıları bundan önce okumanızda fayda var. Bölüm1 ve Bölüm2 den sonra buraya devam ederseniz daha tatmin edici olacaktır sizin için 🙂
Önce şu bahsettiğim ve aslında şurada yazılmış olan ve çok hoşuma giden matefordan bahsedelim 🙂 Bir developer için .NetStandard ın, tüm .NetPlatformlarının implemente etmesi gereken API lar bütünü olduğundan bahsetmiştik. Yan, bu durumda her bir .NetStandard versiyonunu bir interface, her bir .Net Platformunu da bir concerete class olarak düşünmek yanlış olmaz 🙂
Bu durumda da aslında şöyle bir .cs dosyası ile tüm NetStandard versiyonlarını ve onu implemente eden platformları yazabiliriz.
Önce .NetStandard ı görelim;
// .NET Standard interface INetStandard10 { void Primitives(); void Reflection(); void Tasks(); void Collections(); void Linq(); } interface INetStandard11 : INetStandard10 { void ConcurrentCollections(); void EventSource(); void InteropServices(); } interface INetStandard12 : INetStandard11 { void ThreadingTimer(); } interface INetStandard13 : INetStandard12 { void AppContext(); void Console(); void StringInterpolation(); void Calendars(); void FileSystem(); void Sockets(); void AsyncLocal(); } interface INetStandard14 : INetStandard13 { void CryptoECDsa(); } interface INetStandard15 : INetStandard14 { void EventCounter(); } interface INetStandard16 : INetStandard15 { void LinqInterpretation(); void CryptoECCurve(); void PrecompiledRegex(); } interface INetStandard20 : INetStandard16 { void EverythingThatIsInNetFrameworkAndXamarin(); }
yukarıda gördüğünüz ve daha önce söylediğimiz gibi, .NetStandard versiyonları PCL den farkli olarak lineer bir şekilde gidiyor. Her bir versiyonda da, platformların implemente etmesi gerektiğini düşündükleri (required olarak label ladıkları API ları görüyorsunuz)
Peki birde .NetFramework ve .NetCore implementasyonlarına bakalım;
// .NET Framework class NetFramework45 : INetStandard11 { // ... } class NetFramework451 : NetFramework45, INetStandard12 { // ... } class NetFramework452 : NetFramework451 { // ... } class NetFramework46 : NetFramework452, INetStandard13 { // ... } class NetFramework461 : NetFramework46, INetStandard20 { // ... } class NetFramework462 : NetFramework461 { // ... } class NetFramework47 : NetFramework462 { // ... } class NetFramework471 : NetFramework47 { // ... } // .NET Core class NetCore10 : INetStandard16 { // ... } class NetCore11 : NetCore10 { // ... } class NetCore20 : NetCore11, INetStandard20 { // ... }
Burada da, kolayca .NetStandard 2.0 ın Framework 4.6.1 tarafından tamamen implemente edildiğini, aynı şekilde .NetCore1.0 ın NetStandard 1.6 yı implemente ettiğini, .NetCore 2.0 ın da .NetStandard 2.0 ı tamamen implemente ettiğini görüyorsunuz:)
Bir yazılımcı için anlaşılması çok daha kolay oldu değil mi 🙂
Bir de .NetCore CLI kullanarak küçük bir örnek yapalım, Visual Studio 2017 den sonra zaten bunu IDE üzerinden yapmayı göstermenin bir lüzumu yok 🙂 . Hem Cross Platform Command Line Interface i biraz kullanmış tanımış oluruz, hemde hakkında bu kadar yazdığımız .NetStandard ı bir de kod tarafından görmüş oluruz.
Öncelikle Windows tarafında Command Prompt u, Mac tarafında da ise Terminal i açıyoruz. Windows tarafı ile Mac tarafında hiçbir kod farklı olmadığı, yazanları iki tarafta da rahatça deneyebilirsiniz.
İlk olarak aşağıdaki kodu çalıştırarak yeni bir class library projesi oluşturuyoruz. bu proje otomatik olarak .NetStandard olarak oluşacaktır.
$ dotnet new classlib -o mystandardlibrary
bu şekilde bir standard class library projesi oluşturmuş olduk. Şimdi Class1 in içeriğini değiştirip basit bir static metod koyalım.
using System; namespace mystandardlibrary { public class Class1 { public static string GetMessage() => "Hello from .NET Standard!"; } }
Şimdi aşağıdaki komut satırını çalıştırarak yeni bir aspnet core projesi oluşturalım. web keyword ü ile default bir aspnet core projesi oluşacak.
$ dotnet new web -o aspnetcoreclient
Oluşturmuş olduğumuz web projesine, class library projesini referans olarak verelim.
$ dotnet add reference ../mystandardlibrary/mystandardlibrary.csproj
Şimdi de son olarak, web projesindeki Startup.cs dosyasında bulunan inline yazılmış ve gelen request e direk cevap veren tek middleware kodunu edit leyip, aşağıdaki gibi, standard class librarydeki metodumuzu kullanacak şekilde düzenleyelim.
app.Run(async (context) => { var message = mystandardlibrary.Class1.GetMessage(); await context.Response.WriteAsync(message); });
Son olarak, web projesi içerisindeyken önce “dotnet build” projemizi derleyip, sonrada aşağıdaki komut satırını çalıştırarak web projesini ayağa kaldıralım.
$ dotnet run
resimde görmüş olduğunuz gibi http ve https portları üzerinde sitemiz 5000 ve 5001 portlarında ayağa kalktı. Browser ımızı açıp http://localhost:5000 adresine gidersek aşağıdaki gibi, web projemizin, NetStandard kütüphanemizdeki kodu çalıştırdığını göreceğiz.
Birkaç satır kod ile, tüm .Net Platformlarında kullanabileğimiz .NetStandard2.0 kütüphanemizi oluştumuş ve bir aspnet core projesinde kullanmış olduk. 🙂 Bu 3 yazılık seri de, Genel olarak kod paylaşımını, NetStandard ı ve onun diğer .Net platformlar ile olan ilişkisini anlatmaya çalıştım.Umarım keyif almışsınızdır.
.Net Core ile ilgili detaylı yazı serilerinde 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