在程式設計中,常常會遇到會給使用者透過CheckBox的方式,來選取是否開否指定的屬性,
針對這些設定,有許多種寫程式的方法,之前Dotjum常看到的方式,都是如果有五個要自行設定的屬性,
那就會在資料表中開好五個對應的欄位,但這樣的處理,針對未來自行設定資料的增加,勢必資料表欄位要重新調整,而採取 Enum 的方式,只需要一個欄位,未來再增加多少個設定屬性,都只需一個欄位,而且也能夠讓程式撰寫中,能夠更清晰的表達出自行設定欄位的定義。
摘要:
在程式設計中,常常會遇到會給使用者透過CheckBox的方式,來選取是否開否指定的屬性,
針對這些設定,有許多種寫程式的方法,之前Dotjum常看到的方式,都是如果有五個要自行設定的屬性,
那就會在資料表中開好五個對應的欄位,但這樣的處理,針對未來自行設定資料的增加,勢必資料表欄位要重新調整,
而採取 Enum 的方式,只需要一個欄位,未來再增加多少個設定屬性,都只需一個欄位,而且也能夠讓程式撰寫中,
能夠更清晰的表達出自行設定欄位的定義。
介紹:
這一段時間,開始接觸使用類似Entity的概念開發方式,來做系統的開發,對Dotjum來說改變很大,
在資料的傳遞及邏輯的判斷方面,很蠻多不同於自己之前的學習,而在長期的跟 瓶水相逢.Net 請益,
也慢慢的有些成長,希望透過第一篇透過「使用 Enum 來做多選項設定應用」能夠慢慢的介紹關於
Dotjum所瞭解的Entity的概念開發方式,當然本篇跟Entity的概念開發方式比較沒有太多的介紹,
主要還是在Enum的應用面,在之後的文章中,在介紹Dotjum自己用Entity的概念開發方式得心得。
之前 瓶水相逢.Net 所介紹 Enum 的設計與應用 - 簡易權限設計 ,有詳細的介紹 Enum在權限相關的使用,
而本篇Dotjum介紹使用的方法,設定的情境,是使用者管理介面中可以透過CheckBox勾選的方式,
來選取他是否要在顯示自己的相關資料在特定的公開網頁。
如同摘要所說明的,之前Dotjum會採用的方式,可能直接在資料表,開好四個對應的權限欄位,
但有可能過幾天,增加了新的欄位的時候,就會影響到資料表的ER。
而如何採用一個欄位來記住的方式呢?Dotjum這邊先想到的方法就是用Enum的方式,
首先,要先在做出一支設定的 Enum AccessConfig.cs
AccessConfig.cs 的目的是用來在程式中,用來做位元計算。
public enum AccessConfig
{
None = 0,
OpenTel = 1,
OpenFax = 2,
OpenWebSite = 4,
OpenEmail = 8
}
再來就是建立一個 TestMember.cs ,這邊關於Entity的概念開發方式,就簡單的跟各位介紹,
這邊先建立一個 TestMember 的類別,針對剛剛圖中所顯示的四個選取資料的屬性,做一個設定,
而重點就是在於 取的參數資訊 AccessPropertyCheck 及 設定參數資訊 AccessConfigSetter,
這邊先說明在 AccessConfig.cs 中,他是利用位元組的概念,所以在設定中可以看到
OpenTel = 1 = 0001
OpenFax = 2 = 0010
OpenWebSite = 4 = 0100
OpenEmail =8 = 1000
所以我們用文字來模擬 AccessPropertyCheck 的流程,
在AccessPropertyCheck 使用 & 會針對其運算元進行邏輯 AND 運算,
所以會與傳入的參數做邏輯 AND 運算。
如果目前是 0001 (1) ,傳入的值是 1000 (8)
目前 0001 (1)
傳入 1000 (8)
--------------
結果 1001 (9)
在 AND 運算後,會變成 1001 ,在判斷是否跟傳入的 1000 相等,
在這個範例中本來只有開放 OpenTel 當傳入 OpenEmail ,
是詢問 OpenEmail 是否有開放,傳出的資料則為 false,OpenEmail 沒有開放。
而設定參數方面 AccessConfigSetter ,則是傳入設定哪一個參數及bool
在是要開啟設定(true)時,使用 | 會針對其運算元進行邏輯 OR 運算
如果目前是只選 0001 (1)傳入值是 1000 (8)
目前 0001 (1)
傳入 1000 (8)
--------------
結果 1001 (9)
則 OR 運算後,會變成 1001,再將值給入本身的 AccessConfig 設定,
在這個範例中本來只有開放 OpenTel ,當傳入要開啟 OpenEmail ,
整個設定檔的值就會變成 1001 (9),儲存到 AccessConfig 設定。
當開啟設定(false)時,則是先使用~ 運算子會在運算元上執行反轉每個位元的位元補數運算,
在進行 邏輯 AND 運算。
目前 1001 (1)
~傳入1000 (9)
--------------
結果 1000(8)
在這個範例中本來開放了 OpenTel 、OpenEmail ,當傳入要取消 OpenTel ,
整個設定檔的值就會變成 1000(8),儲存到 AccessConfig 設定。
using System;
/// <summary>
/// School 的摘要描述
/// </summary>
public class TestMember
{
public TestMember()
{
}
//設定針對前UI的四個屬性
public bool IsOpenTel
{
get { return AccessPropertyCheck(AccessConfig.OpenTel); }
set { AccessConfigSetter(AccessConfig.OpenTel, value); }
}
public bool IsOpenFax
{
get { return AccessPropertyCheck(AccessConfig.OpenFax); }
set { AccessConfigSetter(AccessConfig.OpenFax, value); }
}
public bool IsOpenWebSite
{
get { return AccessPropertyCheck(AccessConfig.OpenWebSite); }
set { AccessConfigSetter(AccessConfig.OpenWebSite, value); }
}
public bool IsOpenEmail
{
get { return AccessPropertyCheck(AccessConfig.OpenEmail); }
set { AccessConfigSetter(AccessConfig.OpenEmail, value); }
}
private AccessConfig _AccessConfig = AccessConfig.None;
public AccessConfig AccessConfig
{
get { return this._AccessConfig; }
set { this._AccessConfig = value; }
}
//取的參數資訊
protected bool AccessPropertyCheck(AccessConfig ac)
{
//& 會針對其運算元進行邏輯 AND 運算
//如果目前是 0001 (1) ,傳入的值是 1000 (8)
//則 AND 運算後,會變成 1001 ,在判斷是否跟傳入的 1000 相等
return (this.AccessConfig & ac) == ac;
}
//設定參數資訊
protected void AccessConfigSetter(AccessConfig ac, bool select)
{
if (select)
{
// | 會針對其運算元進行邏輯 OR 運算
//如果目前是只選 0001 (1)傳入值是 1000 (8)
//則 OR 運算後,會變成 1001,再將值給入本身的 AccessConfig 設定
this.AccessConfig = AccessConfig | ac;
}
else
{
// ~ 運算子會在運算元上執行反轉每個位元的位元補數運算
//如果目前是只選 0001 (1)傳入值是 0001 (1)
//則 ~ 運算後,會變成 0000,再將值給入本身的 AccessConfig 設定
this.AccessConfig = AccessConfig & ~ac;
}
}
}
在剛剛這麼多說明後,在使用上如何使用呢?
protected void Button1_Click(object sender, EventArgs e)
{
//模擬從資料庫中給值流程
//先建構出 TestMember
TestMember member = new TestMember();
//模擬給值 10 開放 OpenFax 及 OpenEmail
member.AccessConfig = (AccessConfig)10;
Response.Write("OpenTel:" + member.IsOpenTel.ToString() + "---OpenTel = 1" + "<br/>");
Response.Write("OpenFax:" + member.IsOpenFax.ToString() + "---OpenFax = 2" + "<br/>");
Response.Write("OpenWebSite:" + member.IsOpenWebSite.ToString() + "---OpenWebSite = 4" + "<br/>");
Response.Write("OpenEmail:" + member.IsOpenEmail.ToString() + "---OpenEmail = 8" + "<br/>");
Response.Write("AccessConfig:"+ member.AccessConfig.ToString());
}
執行顯示畫面
protected void Button2_Click(object sender, EventArgs e)
{
//模擬給值到資料庫
TestMember member = new TestMember();
member.IsOpenTel = true; //OpenTel = 1,
member.IsOpenFax = true; //OpenFax = 2,
member.IsOpenWebSite = false; // OpenWebSite = 4,
member.IsOpenEmail = true; // OpenEmail = 8
Response.Write("OpenTel:" + member.IsOpenTel.ToString() + "---OpenTel = 1" + "<br/>");
Response.Write("OpenFax:" + member.IsOpenFax.ToString() + "---OpenFax = 2" + "<br/>");
Response.Write("OpenWebSite:" + member.IsOpenWebSite.ToString() + "---OpenWebSite = 4" + "<br/>");
Response.Write("OpenEmail:" + member.IsOpenEmail.ToString() + "---OpenEmail = 8" + "<br/>");
Response.Write("AccessConfig:" + member.AccessConfig.ToString());
}
透過這樣設定的方式,就能夠將多個自訂的CheckBox屬性,使用一個欄位的方式,儲存到資料庫,
而在UI檢視資料的時候,也可以直接透過 if(member.Isxxxx) 的方式,來決定是否要顯示資料,
而未來在增加新的CheckBox屬性時,就更動的範圍不會到ER資料表這邊,當然.cs這邊不管這樣,
一定都要增加對應的屬性,來針對新的CheckBox欄位,給UI做資料的存取。
參考資料:
Enum 的設計與應用 - 簡易權限設計
http://subtextproject.com/