Platformlar Arası Geliştirme için CSCS Komut Dosyası Dilini Kullanma

Yayınlanan: 2022-03-10
Kısa özet ↬ Bu makalede Vassili Kaplan, platformlar arası mobil uygulamalar geliştirmek için bir betik dilini nasıl kullanabileceğinizi açıklıyor. Ekrana widget yerleştirme, SQLite, Web İstekleri ve JSON ayrıştırmayı içeren hem iOS hem de Android'de örnekler bulacaksınız.
Amacımız bir platform oluşturmak değil; hepsini geçmektir.

- Mark Zuckerberg

CSCS (C#'ta Özelleştirilmiş Komut Dosyası), C#'ta uygulanan açık kaynaklı bir komut dosyası dilidir. Sözdizimsel olarak JavaScript'e çok benzer, ancak Python ile de bazı benzerlikleri vardır. Bu benzerliklerden bazıları, iyi bilinen if…elif…else yapısındaki anahtar kelimelerdir ve ayrıca Python'dakiyle aynı değişken kapsam tanımına sahiptir (örneğin, bir if bloğunun içinde veya bir döngünün içinde tanımlanan bir değişken, dışarıda da görünür olacaktır) .

JavaScript ve Python'un aksine, CSCS'deki değişkenler ve işlevler büyük/küçük harfe duyarsızdır. CSCS'nin birincil amacı, geliştiricinin mümkün olduğunca az kod yazmasına izin vermektir . Ayrıca, aynı kod hem iOS hem de Android geliştirme için kullanılır. Ek olarak, CSCS Windows, Mac ve Unity geliştirme için kullanılabilir.

Not : Microsoft'un Maquette ürününde (Unity tabanlı) CSCS'yi nasıl kullandığı hakkında daha fazla bilgiyi buradan edinebilirsiniz.

CSCS, C# kaynak kodunu bir Visual Studio Xamarin projesine gömerek projenize eklenebilir. Diğer dillerin çoğundan farklı olarak, CSCS kaynak kodunun tam mülkiyetine sahipsiniz ve işlevselliğini kolayca ekleyebilir veya değiştirebilirsiniz. Bunun bir örneğini yazının devamında paylaşacağım.

Ayrıca, CSCS'ye nasıl başlayacağımızı öğreneceğiz ve diğer makalelerde ele alınan bazı daha gelişmiş özellikleri kullanacağız. Bu özellikler arasında, JSON dize ayrıştırma ile Web İstekleri aracılığıyla bir Web Hizmetine erişeceğiz ve ayrıca iOS ve Android'de SQLite kullanacağız.

Başlamanın en kolay yolu, CSCS kullanarak bir proje örneğini indirmek ve start.cscs dosyasıyla oynamaya başlamaktır. Bir sonraki bölümde yapacağımız şey budur: temel GUI ve olaylarla bir iOS/Android uygulaması oluşturmak.

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

"Selam Dünya!" CSCS'de

Birkaç widget içeren bir ekran oluşturan nispeten basit bir CSCS kodu örneği ile başlayalım:

 AutoScale(); SetBackgroundColor("light_green"); locLabelText = GetLocation("ROOT", "CENTER", "ROOT", "TOP"); AddLabel(locLabelText, "labelText", "Welcome " + _DEVICE_INFO_ + " " + _VERSION_INFO_ + " User!", 600, 100); locTextEdit = GetLocation("ROOT", "LEFT", labelText, "BOTTOM"); AddTextEdit(locTextEdit, "textEdit", "Your name", 320, 80); locButton = GetLocation(textEdit,"RIGHT",textEdit, "CENTER"); AddButton(locButton, "buttonHi", "Hello", 160, 80); function buttonHi_click(sender, arg) { name = getText(textEdit); msg = name != "" ? "Hello, "+ name + "!" : "Hello, World!"; AlertDialog("My Great App", msg); }

Aşağıdaki resim, “Merhaba” düğmesine tıkladıktan ve “Metin Düzenleme” alanına hiçbir şey yazmadıktan sonra bir iPhone'da ve bir Android cihazında ortaya çıkan kullanıcı arayüzünü göstermektedir:

Selam Dünya!" iPhone'da (solda) ve Android'de (sağda)
"Selam Dünya!" iPhone'da (solda) ve Android'de (sağda) (Geniş önizleme)

Yukarıdaki kodu kısaca gözden geçirelim. AutoScale() işlev çağrısı ile başlar ve bunun yaptığı şey, ayrıştırıcıya pencere öğesi boyutlarının ekran boyutuna göre olduğunu, yani bunların otomatik olarak yeniden boyutlandırılacağını söylemektir (widget daha büyük ekranlarda daha büyük, daha küçük ekranlarda daha küçük görünecektir). ekranlar). Bu ayar, her bir widget için de geçersiz kılınabilir.

Bir düğme tıklamasıyla özel bir işleyici oluşturmaya gerek olmadığını unutmayın. widgetName_click() adında bir işlev tanımlarsanız, kullanıcı widgetName adlı bir widget'ı tıkladığında işleyici olarak kullanılır (bir düğme olması gerekmez, aslında herhangi bir widget olabilir). Bu nedenle buttonHi_click() işlevi, kullanıcı düğmeye tıkladığı anda tetiklenecektir.

GUI'nin tamamen kodda oluşturulduğunu fark etmiş olabilirsiniz. Bu, eklenirken göreli bir pencere öğesi konumu sağlanarak yapılır. Bir konum komutunun genel biçimi şu şekildedir:

 location = GetLocation(WidgetX, HorizontalPlacement, WidgetY, VerticalPlacement, deltaX=0, deltaY=0, autoResize=true);

Böylece, ekrandaki diğer widget'lara göre bir widget yerleştirebilirsiniz. Widget'ın özel bir durumu, ana ekran anlamına gelen "ROOT" widget'ıdır.

Bir konum oluşturduktan sonra, onu aşağıdaki işlevlerden herhangi birine argüman olarak sağlamanız gerekir:

  • AddLabel ,
  • AddButton ,
  • AddCombobox ,
  • AddStepper ,
  • AddListView ,
  • AddTextView ,
  • AddStepper ,
  • AddImageView ,
  • AddSlider ,
  • AddPickerView ,
  • ve bunun gibi.

Yukarıdakilerin tümü aynı yapıya sahiptir:

 AddButton(location, newWidgetname, initialValue, width, height);

AutoScale() CSCS komutu daha önce çalıştırılmışsa, widget genişliği ve yüksekliği ekran boyutuna göre olacaktır. Ayrıca başlangıç ​​değeri (bir düğme olması durumunda) üzerinde gösterilen metindir. Bu, SetText(widgetName, newText) herhangi bir zamanda değiştirilebilir.

CSCS Hatalarını Ayıklamak için Visual Studio Kodunu Kullanma

CSCS betiklerinde hata ayıklamak için Visual Studio Code'u da kullanabiliriz. Hem Android hem de iOS için uygulamalar geliştirmek istiyorsanız, bir Mac kullanmanız gerekir. Visual Studio Code'u yükledikten sonra CSCS Debugger ve REPL uzantısını yükleyin.

Uzantıyı kullanmak için bu kod satırını start.cscs CSCS komut dosyanızın herhangi bir yerine ekleyin:

 StartDebugger();

Aşağıdaki resim, "Merhaba, Dünya!"nın işlevselliğini hata ayıklamak ve değiştirmek için Visual Studio Code'u nasıl kullanabileceğinizi gösterir. önceki bölümde geliştirdiğimiz uygulama. Yaklaşan örnekte, mevcut düzene anında bir etiket ve bir düğme ekleyeceğiz.

Bunu yapmak için, ayrıştırıcı tarafından yürütülecek kodu seçip Ctrl + 8 tuşlarına basıyoruz. Sonuç olarak, ekranın ortasına bir etiket ve bir düğme eklenecektir. Ayrıca, her düğme tıklamasında yeni etiketi geçerli saatle güncelleyecek bir düğme işleyicisi ekledik.

Visual Studio Code ile Anında Düzeni Değiştirme
Visual Studio Code ile Anında Düzeni Değiştirme (Geniş önizleme)

CSCS'de SQLite Kullanmak

SQLite, ilişkisel bir veritabanının ACID (Atomicity, Consistency, Isolation, Durability) tipidir ve Richard Hipp tarafından geliştirilmiştir (ilk sürüm 2000'de yayımlanmıştır). Microsoft SQL Server veya Oracle Database gibi diğer ilişkisel veritabanlarından farklı olarak gömülüdür. (Yalnızca cihaza değil, aynı zamanda son programa da gömülüdür.) Boyut olarak 500 KB'den küçük, çok kompakt bir kitaplık olarak programa dahil edilmiştir. Ancak, DB dosya yolu her iki uygulama tarafından da biliniyorsa, iki uygulama (aynı geliştirici tarafından yayınlanmıştır) aynı SQLite DB'sini okuyabilir.

SQLite'ın avantajı, bir iOS veya Android cihazında ekstra bir kurulum olmadan kullanılabilmesidir. Dezavantajı, açıkça "normal" bir DB kadar fazla veri tutamaması ve ayrıca zayıf yazılmış olmasıdır (yani, bir tamsayı yerine bir dize ekleyebilirsiniz - daha sonra bir tamsayıya veya hata durumunda 0'a dönüştürülür). Öte yandan, ikincisi de bir avantaj olarak görülebilir.

SQLite, fazladan içe aktarma ifadeleri olmadan CSCS'den kolayca kullanılabilir. CSCS'de kullanılan ana SQLite işlevlerine genel bir bakış elde etmenize yardımcı olacak bir tablo:

Emretmek Tanım
SQLInit(DBName) Bir veritabanını başlatır veya sonraki DB ifadeleriyle kullanılacak bir veritabanını ayarlar.
SQLDBExists(DBName) DB'nin başlatılıp başlatılmadığını kontrol eder. Ayrıca, sonuç veritabanı deyimleriyle kullanılacak veritabanını da ayarlar.
SQLQuery(query) Bir SQL sorgusu yürütür (bir seçme ifadesi). Kayıtları olan bir tablo döndürür.
SQLNonQuery(nonQuery) SQL sorgusu olmayan bir sorgu yürütür, örneğin bir güncelleme, oluşturma veya silme ifadesi. Etkilenen kayıtların sayısını döndürür.
SQLInsert(tableName, columnList, data) Belirtilen DB tablosuna kayıtların veri tablosunu ekler. columnList bağımsız değişkeni aşağıdaki yapıya sahiptir: colName1,colName2,…,colNameN

Tablo 1: CSCS'de SQLite komutları

SQLInit() ve SQLDBExists() işlevleri tipik olarak şu şekilde kullanılır:

 DBName = "myDB.db1"; if (!SQLDBExists(DBName)) { create = "CREATE TABLE [Data] (Symbol ntext, Low real, High real, Close real, Volume real, Stamp text DEFAULT CURRENT_TIMESTAMP)"; SQLNonQuery(create); } SQLInit(DBName);

Daha sonra bir SQLite veritabanına nasıl veri seçip ekleyebileceğinize dair daha fazla örnek göreceğiz. Size bir Web Hizmetinden çıkarılan stok verilerinin yerel bir SQLite veritabanına nasıl yazılacağının bir örneğini göstereceğim.

CSCS'ye Özel İşlevsellik Ekleme

Bu bölümde, CSCS işlevselliğini nasıl genişletebileceğinizi göreceğiz. Örnek olarak, aşağıda CSCS Uyku fonksiyonunun mevcut uygulamasını göreceğiz.

Özel işlevler eklemek için tek yapmanız gereken, ParserFunction sınıfından türeterek, Evaluate() yöntemini geçersiz kılarak ve bu sınıfı ayrıştırıcıya kaydederek yeni bir sınıf oluşturmaktır. İşte kısa bir versiyon (hata kontrolü olmadan):

 class SleepFunction : ParserFunction { protected override Variable Evaluate(ParsingScript script) { List args = script.GetFunctionArgs(); int sleepms = Utils.GetSafeInt(args, 0); Thread.Sleep(sleepms); return Variable.EmptyInstance; } } class SleepFunction : ParserFunction { protected override Variable Evaluate(ParsingScript script) { List args = script.GetFunctionArgs(); int sleepms = Utils.GetSafeInt(args, 0); Thread.Sleep(sleepms); return Variable.EmptyInstance; } }

Ayrıştırıcı ile bir sınıfın kaydı, aşağıdaki komutla başlatma aşamasında herhangi bir yerde yapılabilir:

 ParserFunction.RegisterFunction("Sleep", new SleepFunction());

Bu kadar! Şimdi, ayrıştırıcı tarafından bir “Sleep” belirteci çıkarılır çıkarılmaz, SleepFunction sınıfının Evaluate() yöntemi çağrılacak.

CSCS'nin büyük/küçük harfe duyarlı olmadığını unutmayın (temel kontrol akışı ifadeleri dışında: if , elif , else , for , while , function , include , new , class , return , try , throw , catch , break , continue ). Bu, "uyku(100)" veya "Uyku(100)" yazabileceğiniz anlamına gelir - her iki çağrı da yürütülmekte olan iş parçacığını 100 milisaniye boyunca askıya alacaktır.

CSCS'de JSON İşleme

JSON (JavaScript Object Notation), nitelik-değer çiftlerinden ve dizi tipi çiftlerinden oluşan hafif bir veri değişim formatıdır. 2000'lerin başında Douglas Crockford tarafından geliştirilmiştir (SQLite'ın da ortaya çıktığı sıralarda).

Bu bölümde, CSCS kullanarak JSON'un nasıl ayrıştırılacağını öğreneceğiz.

Bir JSON dizesini ayrıştırmak için CSCS işlevi GetVariableFromJSON(jsonText) . Bu işlev, anahtarların JSON dizesindeki öznitelikler olduğu bir karma tablo döndürür.

Aşağıdaki bir JSON dizesi örneğini düşünün:

 jsonString = '{ "eins" : 1, "zwei" : "zweiString", "mehr" : { "uno": "dos" }, "arrayValue" : [ "une", "deux" ] }';

Çağırdıktan sonra:

 a = GetVariableFromJSON();

a değişkeni, aşağıdaki değerlere sahip bir karma tablo olacaktır:

 a["eins"] = 1 a["zwei"] = "zweiString" a["mehr"]["uno"] = "dos" a["arrayValue"][0] = "une" a["arrayValue"][1] = "deux"

Bir sonraki bölümde, bir Web Hizmetinden bir JSON dizesini ayrıştırmanın başka bir örneğini göreceğiz.

SQLite, Web İstekleri ve JSON İçeren Bir Uygulama Örneği

SQLite, Web Hizmeti ve JSON ayrıştırma kullanan bir uygulama için Alpha Vantage Web Hizmetini kullanacağız. Bir API Anahtarını ücretsiz olarak alabilirsiniz, ancak ücretsiz sürüm, web hizmetlerine dakikada en fazla 5 kez erişime izin verir.

Alpha Vantage'ı kullanarak, hisse senedi fiyatları da dahil olmak üzere çeşitli finansal veri kümelerini çıkarabilirsiniz. Örnek uygulamamızda yapacağımız şey bu.

Aşağıdaki resim, Hisse Senetleri uygulamalarının bir iOS ve bir Android cihazda nasıl göründüğünü gösterir.

iOS (solda) ve Android'de (sağda) Alpha Vantage Web Hizmetinden Hisse Senetlerini Çıkarma
iOS (solda) ve Android'de (sağda) Alpha Vantage Web Service'ten Hisse Senetlerini Çıkarma (Geniş önizleme)

GUI'yi oluşturmak için CSCS kodu aşağıdaki gibidir:

 locLabel = GetLocation("ROOT","CENTER", "ROOT","TOP", 0,30); AddLabel(locLabel, "labelRefresh", "", 480, 60); locSFWidget = GetLocation("ROOT","CENTER", labelRefresh,"BOTTOM"); AddSfDataGrid(locSFWidget, "DataGrid", "", graphWidth, graphHeight); listCols = {"Symbol","string", "Low","number", "High", "number", "Close","number", "Volume","number"}; AddWidgetData(DataGrid, listCols, "columns"); colWidth = {17, 19, 19, 19, 26}; AddWidgetData(DataGrid, colWidth, "columnWidth"); locButton = GetLocation("ROOT","CENTER",DataGrid,"BOTTOM"); AddButton(locButton, "buttonRefresh", "Refresh", 160, 80); locLabelError = GetLocation("ROOT","CENTER","ROOT","BOTTOM"); AddLabel(locLabelError, "labelError", "", 600, 160); SetFontColor(labelError, "red"); AlignText(labelError, "center"); getDataFromDB();

getDataFromDB() yöntemi, SQLite veritabanındaki tüm verileri çıkaracaktır. Aşağıdaki gibi tanımlanan SQL sorgusunu kullanır:

 query = "SELECT Symbol, Low, High, Close, Volume, DATETIME(Stamp, 'localtime') as Stamp FROM Data ORDER BY Stamp DESC LIMIT 5;";

getDataFromDB() uygulaması için aşağıdaki koda bir göz atın.

 function getDataFromDB() { results = SQLQuery(query); for (i = 1; i < results.Size; i++) { vals = results[i]; stock = vals[0]; low = Round(vals[1], 2); high = Round(vals[2], 2); close = Round(vals[3], 2); volume = Round(vals[4], 2); refresh = vals[5]; stockData = {stock, low, high, close, volume}; AddWidgetData(DataGrid, stockData, "item"); } SetText(labelRefresh, "DB Last Refresh: " + refresh); lockGui(false); }

Şimdi Alpha Vantage Web Service'ten nasıl veri alacağımıza bakalım. İlk olarak, verileri başlatıyoruz:

 baseURL = "https://www.alphavantage.co/query? " + "function=TIME_SERIES_DAILY&symbol="; apikey = "Y12T0TY5EUS6BC5F"; stocks = {"MSFT", "AAPL", "GOOG", "FB", "AMZN"}; totalStocks = stocks.Size;

Ardından, kullanıcı “Yenile” düğmesine tıkladığında stokları tek tek yükleriz:

 function buttonRefresh_click(object, arg) { lockGui(); SetText(labelRefresh, "Loading ..."); SetText(labelError, ""); ClearWidget(DataGrid); loadedStocks = 0; getData(stocks[loadedStocks]); } function getData(symbol) { stockUrl = baseURL + symbol + "&apikey=" + apikey; WebRequest("GET", stockUrl, "", symbol, "OnSuccess", "OnFailure"); }

Bir Web Hizmetinden veri almak için kullanılacak ana CSCS işlevi:

 WebRequest("GET", stockUrl, "", symbol, "OnSuccess", "OnFailure");

Son iki parametre, web isteğinin tamamlanması üzerine çağrılacak işlevlerdir. Örneğin, bir arıza durumunda aşağıdaki CSCS işlevi çağrılır:

 function OnFailure(object, errorCode, text) { SetText(labelError, text); lockGui(false); }

Sonuç olarak, kullanıcı aşağıda gösterildiği gibi bir hata mesajı alacaktır:

Web verileri istenirken bir hata
Web verileri istenirken bir hata (Büyük önizleme)

Ancak, her şey yolundaysa, JSON dizesini ayrıştıracağız ve içeriğini SQLite DB'ye ekleyeceğiz.

 function OnSuccess(object, errorCode, text) { jsonFromText = GetVariableFromJSON(text); metaData = jsonFromText[0]; result = jsonFromText[1]; symbol = metaData["2. Symbol"]; lastRefreshed = metaData["3. Last Refreshed"]; allDates = result.keys; dateData = result[allDates[0]]; high = Round(dateData["2. high"], 2); low = Round(dateData["3. low"], 2); close = Round(dateData["4. close"], 2); volume = dateData["5. volume"]; stockData = {symbol, low, high, close, volume}; SQLInsert("Data","Symbol,Low,High,Close,Volume",stockData); if (++loadedStocks >= totalStocks) { getDataFromDB(); } else { getData(stocks[loadedStocks]); } }

Yukarıdaki hash tablosundaki farklı alanlara nasıl eriştiğimizi anlamak için Alpha Vantage web isteğinden alınan gerçek dizeye bir göz atalım:

 { "Meta Data": { "1. Information": "Daily Prices (open, high, low, close) and Volumes", "2. Symbol": "MSFT", "3. Last Refreshed": "2019-10-02 14:23:20", "4. Output Size": "Compact", "5. Time Zone": "US/Eastern" }, "Time Series (Daily)": { "2019-10-02": { "1. open": "136.3400", "2. high": "136.3700", "3. low": "133.5799", "4. close": "134.4100", "5. volume": "11213086" }, … } }

Gördüğünüz gibi, çıkarılan tüm tarihleri ​​içeren allDates dizisinin ilk öğesi olarak en son tarihi alıyoruz.

Çözüm

Projenize CSCS eklemek kolaydır. Yapmanız gereken tek şey, CSCS'nin kaynak kodunu bir modül olarak projenize gömmek - tıpkı örnek bir Xamarin projesinde olduğu gibi.

Projelerinizde CSCS betik dilini kullanıyor ve genişletiyor musunuz? Aşağıya bir yorum bırakın - Sizden haber almaktan memnuniyet duyarım!

Daha fazla okuma

CSCS dilini biraz daha keşfetmek isterseniz, konuyla ilgili yazdığım makalelerden bazıları şunlardır:

  • “C#'ta Böl ve Birleştir İfade Ayrıştırıcısı,” MSDN Magazine (Ekim 2015)
  • “C#'ta Özelleştirilebilir Komut Dosyası”, MSDN Dergisi (Şubat 2016)
  • “Özelleştirilebilir Bir Komut Dosyası Dili Kullanarak Yerel Mobil Uygulamalar Yazma,” MSDN Magazine (Şubat 2018)
  • "CSCS: C#'da Özelleştirilmiş Komut Dosyası Oluşturma" GitHub
  • “İşlevsel Komut Dosyası Diliyle Platformlar Arası Yerel Uygulamalar Geliştirme” CODE Dergisi
  • “Özel Bir Dili Özlü Şekilde Uygulamak” (e-Kitap)
  • “Yerel Mobil Uygulamaları İşlevsel Bir Dilde Kısa ve Öz Bir Şekilde Yazma” (e-Kitap)

Ek bir kaynak olarak, işlevlerini önceden derleyerek CSCS performansını nasıl iyileştirebileceğinizi de okumanızı tavsiye ederim.