包含標籤 CSharp 的文章

C#: 使用 System.Environment 取得環境資訊、特殊資料夾路徑

有時候我們會需要取得一些系統資訊,例如說取得設備和當前使用者等資料來寫 Log,或是取得特殊資料夾路徑、讀取環境變數等等。這些時候就可以使用 System.Environment ,這邊就稍微紀錄一下用法。

先列出幾個常用的環境資訊,詳細可查詢的內容可以到 Environment Class 查詢:

資料夾路徑則需要用 Environment.GetFolderPath 搭配 Environment.SpecialFolder 列舉使用,該列舉包含資料夾可以到 Environment.SpecialFolder Enum 查詢。

……

閱讀全文


C#: 程式碼風格備忘

前言:本篇是整理公司規範和網路文章後,方便我自己在各個場所也能回來查閱使用的,故仍會不定時修改(畢竟我這人挺三心二意的)。另外本篇有重新調整過行距,發現有點跑版的朋友可以先 Ctrl+F5 一下,感謝閱讀。

如果你想知道的是如何寫出更優雅、更乾淨、品質更高的程式碼,那並不是該看這篇我個人的備忘錄,我會建議可以閱讀《無暇的程式碼》。或是可以參考這幾篇,我覺得都寫得很好:可不可以不要寫糙 codeClean Code 無瑕的程式碼閱讀筆記易讀程式之美學,共勉之。

如果你是正巧路過並且也寫 C#,希望這篇能讓你做為參考。但請記得,程式碼風格沒有絕對,最終還是回歸到團隊能否接受和將來的可維護性去考慮,畢竟教條是死的,人是活的。了解這樣做背後的原因,以及為自己寫的程式碼負責,這些都比對著隻字片語斤斤計較更加重要。

Nothing is true, everything is permitted. —— Assassin’s creed.

命名原則

想像下一個接手你程式碼的人是個暴力傾向的重度精神病患者

而且他知道你住在哪。  —— 《無瑕的程式碼》

  • 使用有意義的命名,請重視描述性。除了迴圈計數器例外
  • 盡量不要超過五個單字
  • 業界和慣例中有對應縮寫時可以使用縮寫
  • 承上,縮寫兩個字母時全大寫,三個字母以上時只第一字大寫

命名空間

  • 基礎類別庫:{組織} . {大類/應用範圍} . {小類/專案名稱}
    • MyStudio.Libs.Basic
    • MyStudio.Libs.Web.BaseTools
  • 專案類別庫:{專案名稱} . {子專案/類別/用途}
    • MyProject.Permiss.Proxy
    • MyProject.Permiss.Repository
……

閱讀全文


菜雞與物件導向 (2): 建構式、多載

我就直接說了,有用前面的程式碼區塊的人,絕對執行不了。因為我們建立哥布林和戰士這兩張卡片的時候,根本就沒有給他們數值呀!

雖然可以先呼叫出來再賦值…

var goblin = new Card();
goblin.Name = "哥布林";
goblin.Attack = 3;
goblin.Health = 2;
/* ...其他賦值 */

這實在相當占空間,也有點奇怪。畢竟如果是阿福(狗),一出生的時候應該就確定了一些特徵才對,例如品種、血型、眼睛顏色這種。並不會出生後過一陣子,才突然決定這些東西,既然如此,我們在產生物件的時候,當然也會希望在建立的同時就先決定好一部份內容

這時候我們就可以藉由建構式的方式,在建立物件時就進行一些我們想要的操作。

建構式

事實上,當我們呼叫 new Card() 的時候(不覺得這個 () 很有呼叫方法的感覺嗎?)我們就是正在調用 Card 的建構式。而當我們沒有特別去定義建構式的時候,就會直接使用內建的建構式去幫我們產生物件。

現在我們替 Card 新增一個建構式:

public class Card
{
    public Card (string name, int attack, int health)
    {
        this.Name = name;
        this.Attack = attack;
        this.Health = health;
    }
    /* ... 其他屬性和方法 */
}

在 C# 的時候,建構式必須和類別同名,且不需要定義回傳類型。當我們有了建構式,剛剛的例子就可以改寫成:

var goblin = new Card(name: "哥布林", attack: 3, health: 2);
var warrior = new Card(name: "戰士" , attack: 4, health: 3);
warrior.Hit(goblin);

建構式也就是建立這個物件時執行的函式,通常會用來進行初始化,也就是做一些建立物件必要的準備。例如傳遞必要屬性或是建構需要的其他物件、或是給予私有屬性初始值等等,例如說我們的卡牌一建立,就會需要知道它的名字和戰鬥力,這樣才有卡牌的感覺,而不該像一些 壞決鬥者 邊打牌邊偷偷印卡。

……

閱讀全文


AutoMapper —— 類別轉換超省力

類別間的轉換幾乎是每個專案每個工程師都會碰到的動作,舉凡是分層架構每層之間的轉換,如 Dto 轉換成 ViewModel;或是接收到資料要塞進自定義的類別時也需要進行轉換。但在遠古時代,當我們要把一個類別的資料倒進另一個類別時,總免不了一番折騰

例如一個卡片對戰遊戲的資料庫,光是要先把卡片資料讀取出來就需要:

有些時候也會看見用 Foreach 然後逐一傳值的場景,或是各種差不多的變種情況。同樣的是,光是將一個簡單的卡片資訊轉換成 ViewModel,就花了一大段在做對映的處理。這個過程本身枯燥乏味又占空間,更可怕的是,如果有個陳年資料表,動不動就上百個欄位,那這個轉換過程的恐怖程度可想而知

幸好!天無絕人之路,這種時候就是本日的主角 —— AutoMapper 出場的時候了。

當 AutoMapper 一出手,轉換的過程瞬間就變成:

是不是精簡很多呢?接著就讓我們來看看怎麼開始使用吧!

……

閱讀全文


Electron.net —— 把網頁包成桌面應用吧

因緣際會下想要弄出一些單機小工具來跑,這時候正巧接觸到 Electron.net 這個神器,特別紀錄一下以免忘記。這是 Electron 搭配 .net Core 的框架, Electron 是用 Chromium 和 Node.js 將網頁封裝成桌面應用程式,像是 Visual Studio Code、Slack 也都有使用到 Electron。而 Electron.net 顧名思義就是 .net 用的 Electron 框架囉。

這邊記錄一下自己嘗試時載入套件和建置的流程,主要參考自黑大的 用 ASP.NET Core 寫桌面 GUI 應用程式 - Electron.NETElectron.NET API 快速巡覽 這兩篇文章,以及官方的 API DEMO,特此感謝。

本篇小節:

……

閱讀全文


C#: 位元旗標 (Bit flag) 與列舉

前陣子碰到個資料表儲存方式,因為這種位元運算的方式也常用在權限管理等地方,這邊就順手紀錄一下。

平常遇到二元的情形(例如 開/關、有/沒有),我們會直接宣告個 Boolean 來處理。但這次遇到的是同時有多個「有/沒有」的狀況,但我遇到的程式碼並沒有分成多個 Bool 去做處理,而是直接儲存成一個數值。

由於「有/沒有」只佔據一個位元,那麼將多個狀況按照位元順序排列的話,就只需要一個數字就可以紀錄或傳遞給其他系統了。例如最常見的用處是在權限系統,若有「讀」、「寫」、「執行」等權限,那麼我們按照這個順序去排列,當 讀=可、寫=不可、執行=可 的時候,就記做 101 = 5。這種直接用一組位元表示狀態的方式就叫做位元旗標(Bit flag)

1 讀   = 可
0 寫   = 不可
1 執行 = 可

/* 橫放 */
=> 101 (2進位) 
=> 5 

假使某天老闆靈光一現,決定接下來的新人員工都要記錄他們會的程式語言,並且他們報到的時候就會發一張公司列好的程式語言清單請他們勾選。

Enum & Flags

在 C# 中已經有方便的工具可以處理數字列表,我們可以建立一個叫做 SkillEnum 的列舉(Enum),並且按照上面說明的,將老闆提到的每個技能各自用一個位元來表示。

[Flags]
public enum SkillEnum
{
    C = 1,     // 0001
    PHP = 2,   // 0010
    SQL = 4,   // 0100
    Java = 8,  // 1000
}

註:[Flags]的標籤是指 C# 專門提供給位元旗標使用的 Enum,請參見 FlagsAttribute

只要在 enum 上加上 Flags 的屬性,除了自動按照 2 的次元增加以外,在使用 ToString() 也能更方便看見旗標內容

有了這個列舉之後,我們就可以表達不同排列組合的狀況了。例如:

* C: C
* P: PHP
* S: SQL
* J: Java
===========
J S P C
0 0 0 0 => 什麼都不會
0 0 0 1 => 只會 C
0 0 1 1 => 同時會 C 和 PHP
1 0 1 0 => 同時 PHP 和 Java
1 1 1 1 => 全部都會
……

閱讀全文


EPPlus —— 輕鬆處理 Excel

前陣子工作需要匯出一些資料表,因此用到了 EPPlus 這套工具來把資料匯出成 Excel。由於這需求似乎會挺常遇到的,決定記一下。

目標:稍微紀錄一下這次碰到 EPPlus 的用法。

EPPlus 是在 .NET Framework 或 .NET Core 上提供控制 Excel 的元件,操作簡單好懂,當有需要在網頁上讓人將表格資料下載成 Excel 的功能時就可以試著使用。常常一併被提起的還有另一個一樣老牌的相似功能元件 NPOI,不過我個人只用過 EPPlus 便不再贅述。關於更詳細的介紹,可以參閱黑暗執行緒的這篇 比 NPOI 更討喜的 Excel 元件 - EPPlus!,儘管是有些久遠的文章但仍能迅速了解 EEplus 的賣點和差異。

我在使用 EPPlus 時主要的參考來自於 EPPlus 的 Wiki,每個功能都有說明及範例,同時也有範例專案可以下載,寫得相當詳細。另外還找了如 導出 Excel 之 Epplus 使用教程 - Wico’s Blog使用 EPPLUS 操控 Excel - 碼農的學習日誌 這些有逐步說明的文章,在此感謝。

……

閱讀全文


Asp.net MVC: 連線資料庫、簡單實作 CRUD

在教學時直接使用 EF 對資料庫跑繫結的方式產生各頁面,但得到了「點一點東西就跑出來了搞不懂呀」的回饋,心想有道理。因此從頭開始實作一遍,並記錄下來。(雖然做完還是覺得,直接用 EF 跑的話果然比較安全方便啊)

目標:實作一個 MVC 架構,具資料庫基本操作功能的網站,其中包含連線至資料庫的 model、對其進行調用的 controller 以及顯示的 view。

註:本文預設已在本地電腦上安裝了 SQL Server,並且建立了測試用的資料庫 Test 及表 card,詳情會在文章內述。另外,由於在寫這邊的時候是為了練習手動從編碼開始嘗試連線,故將不使用 EF 連線產生 Edmx 的方式,而是直接手工編寫程式碼進行操作。

另外,關於直接從資料表自動產生可操作的頁面,亦即使用 Entity Framework 做資料繫結的方式,請見 Asp.net MVC 筆記:Entity Framework 連線資料庫

……

閱讀全文


Asp.net MVC: Entity Framework 連線資料庫

目標:將 上一篇的 Asp.net MVC:連線資料庫、簡單實作 CRUD 的資料庫基礎功能改成以 Entity Framework 產生的方式跑一遍

既然上一篇介紹了土法煉鋼動手做的資料庫取值方式,就覺得不順手把從 EF 建立出基本功能介面的方式記錄下來似乎是有點奇怪。實際上開始寫成筆記之後才發現對內容尚不是很了解,例如一直用 Data First 產生頁面但對 Code First 以程式碼產生架構的方式很不熟。儘管如此仍稍微紀錄一下,之後有更深的了解(例如 ASP.NET Identity 或 Code First 等部分)再進一步做成筆記。另外也可參考較詳細的官方文檔

……

閱讀全文