最近的程式設計中,用到滿多Reflection(反映)的做法。
以下我先簡單記錄這陣子的心得,首先先做一個範例說明:
MyLibrary-> Class library project.
WindowsFormsApplication2->Windows form project.
MyLibrary.dll程式碼如下:(建立一個book class)
1.取得對應的Type
一般我們取得的方式都是使用Assembly.GetTypes() 或是 Assembly.GetType(),
這些方式都是滿常用的,今天要介紹的是比較不同的。
其實在Type類別中有一個static GetType(string),這個也可以取得相對應的Type。
執行結果:
2.取得實體物件
在這裡一般書上都會先找出ConstructorInfo這個建構式後在去取得實體物件,如下說明:
執行結果:
今天要記錄的是滿少看到的用法(對我啦! XD),Activator.CreateInstance
執行結果:
3.動態加入事件
這裡是使用EventInfo Class
執行結果:
先簡單記錄到這,以後要補充的再加上!!
2010-12-16
C# Reflection 一些雜項記錄(書中介紹之外的)
Chain Constructors
在Refactoring to Patterns一書中有提到Chain Constructors的觀念,
書中的意思是說,在不同的建構式中,出現重複的程式碼,
可以借由Chain Constructors來將複雜的程式碼簡化
譬如今天建立一個物件,其建構式如下
在MyEmployee的建構式中,提供了三個不同的建構式,
因為對這個MyEmployee的物件中,Telephone與Fax是可有可無的條件,
所以希望是說藉由不同的建構式,來建立適當的物件即可,
但~注意到了嗎?以上的程式碼是不是看得很礙眼?
重複的程式碼不斷的出現在建構式中,其實!!!
我們可以精簡如下:
看~是不是簡單多了??
在最終的建構式中,提供全部的條件需求,
其他的兩個建構式分別去呼叫最終的那個建構式,
這樣不僅是在維護上更加方便,在觀看程式碼的時候也會比較清晰。
簡單記錄下來,提供日後參考。
2010-12-09
WinForm 重構
這次因為新的功能需求,需要改寫之前所撰寫的程式功能,
Business Logic幾乎都沒變動,唯一變動的是UI畫面,
以及前端登入時的一些資料驗證功能,但這些小變更卻花了我不少時間重構。
為什麼呢?請聽我慢慢細說。。。
當初在設計這支程式的時候,是有遵循MVC的設計方式,
該是UI該做的顯示畫面,或是Model該處理的Business Logic都是有相當程度的區隔
但是卻沒有相當嚴謹的遵循,導致有些Logic還是放在UI層,
例如:Form Class裡頭竟然還有Business Logic,當我在重新修改功能的同時,
也順便將這些不該存在的東西全部抽離。
UI層就完全是在顯示資料用,他不需要管底層到底做了哪些事情,
而Model則是完全處理關於Business Logic,這樣把權責給區分出來,
這樣重構下來對以後在維護的時候會更加方便。
另外,再提到一個小觀念,其實這是之前就已經知道的事情,
但是卻還是到現在才又開始想起,我先提一段程式碼。如下所示:
其中tbxName、tbxage是Textbox控制項,一般在寫WinForm的時候,
我在想大部分的人都應該跟我一樣,都很偷懶直接在Button的事件中寫完所有的事情,
不管是方便性來說,或是以後在維護來講其實都挺方便的(只要看這個Method就好)
但是。。。
今天若又有一個Button要提示未滿18或已滿18,
不知道你是不是也會跟我一樣這樣寫?
這樣真的可以Work,但是各位看官,您發現了嗎?
程式裡多了好幾句反覆的程式碼,這樣的寫法很不恰當,
因為萬一又多了一個Button又要做其他功能,是不是又要再寫一次轉換int的程式?
(這裡還不包括是不是會遇到不是int的錯誤)
這裡比較好的作法應該是這樣,設計成屬性
(當然若是只在這個Class中使用請將層級換成private)
這樣的好處是,程式可以重複使用,另外也可以加入驗證機制。
另外寫在Button的程式碼,是不是又更簡單易懂??
這麼簡單的東西,我竟然現在才想到,真的是。。。
記錄下來以後可以這樣設計!!
2010-11-23
自訂PropertyGrid視窗屬性
今天很意外的看到這篇文章
[C#.NET][VB.NET] 自訂控制項的顯示視窗屬性 /User Control of Properties(一)
原本是想查詢[是否能在設計屬性的時候,利用Attribute來設計預設值]
這部分有點像是之前在設計自訂的ConfigurationSection時,
可以設定自己的預設值。
不過,後來問林大哥後,好像是沒有這樣的東西?
我先把這個過程記錄下來,留給以後參考。
另外前面提到這篇文章,之前也看過有機會用到時可以參考。XD
2010-11-18
c#委派寫法(整理心得筆記)
今天一早比較有空的時候,邊吃著早餐邊拜讀Huan-Lian大大寫的這篇文章
Huan-Lin 學習筆記: C# 筆記:重訪委派-從 C# 1.0 到 2.0 到 3.0
(迷之音:早餐配這種很枯燥的東西,不怕沒胃口嗎?XD)
不過還好Huan-Lian大大寫的滿淺顯易懂的,倒是很有趣的帶過整個委派寫法的演變。
先來簡單做個心得筆記,怕自己以後會忘掉,先記錄下來。
首先設計一個資料物件(MyObject)供範例使用。
C# 1.0 委派寫法
C# 2.0 委派寫法
(1) Delegate新寫法
另外甚至於可以直接這樣寫-> objCollection.Find(FindObject2)即可
(2) Anonymous 寫法
C#3.0 委派寫法(這部分就完全是看網頁上說明了!!)
可以簡化寫成如下表示
省略定義targetObj型態和return
看完以上的寫法後,我在想若可以的話以後會盡量使用Lambda寫法。
簡單記錄下,提供以後參考。
2010-11-14
解決專案中不同Naming的問題
問題:
專案遇到一個滿棘手的問題,原本使用者需求希望我們產生的表單編號是(合約編號-四碼流水號)
假設合約編號是XR-332211,那所產生的表單單號為XR-332211-0001,這是原先的需求。
但是需求總是會變動的,這次使用者又覺得說這樣的表單單號太長,因為受限於一些環境需求,
而我們被迫要變動我們的程式。。。
若我們根據新需求來變動,那接下來問題又來了,若是現在這個專案是這樣,另外一個專案又需要另外的命名規則時,
我們是不是又要變動程式碼?這對我們程式設計師來說,最不希望看到的現象[不停的在修改我們的程式]。
解決方案:
跟林大哥討論完之後,他給我一個架構如下
我們在程式裡面針對Naming Rule設計一個合約(INaming),一個很簡單的GetName Method
接下來,我們實際設計一個Naming的物件(NC6Naming),並實作INaming的GetName
在這個物件中,建構式變成很重要的一個角色,
因為這裡需要別的地方提供所有可以供Naming的資料,
(此例中SpoolBaseObj有許多可以提供Naming的資料)
然後在ClientAPI中利用Reflect來操作IName取得表單命名字串。
這樣若往後需要不同的專案時,可以再新增Naming的物件,
只要在ClientAPI中,告訴它要使用的是哪一個Naming物件,就可以不用到修改原始程式碼,
又能接受這樣的需求變更。
一個Class可以同時擁有兩個以上相同的Property或Method
看到這個標題,應該有很多人會感到很疑惑??
(蝦米??一個Class可以有兩個以上相同的Property或Method,怎麼可能?)
其實,若是操作Interface的話,這就不成問題
首先設計兩個不同的Interface(IA、IB),但是設計相同的屬性與Method
再來設計一個Class(TestInterface),並實作IA、IB
接下來實際操作這個物件,但在操作的時候請轉型成IA or IB操作
這樣就可以同一物件兩個以上相同屬性的操作
結果
這要使用在真正的設計中,其實還沒有頭緒??該用在哪?
我在想若是要使用來擴充新Method時,
但是卻遇到與之前所設計的Method有相同名稱時,可以借由這個方式另外操作??
(Method無法被Override的時候,只是那既然這樣到不如就設計一個新的Method就好?)
或許以後會有新的看法,先記錄下來。
2010-06-16
複習使用Attribute方法
已經很久沒使用Attribute的方式來設計程式,
今天有一個新專案正好可以適用到這個架構,
乾脆就順便來記錄一下,題外話結束。
1.首先建立一個Class並繼承Attribute
1: public class InfoAttribute:Attribute
2.並設定AttributeUsage屬性
1: [AttributeUsage(AttributeTargets.Class)]
2: public class InfoAttribute:Attribute
3.建立建構式(Constructor),到這一步驟其實設計已經完成。
1: public InfoAttribute(string BOName, ClassificationType mDocType)
2:
3: {
4: BONameField = BOName;
5: mDocTypeField = mDocType;
6: }
4.在自訂的Class上設定屬性資訊,可以看到下例兩個設定值,這是建構式所需要的。
1: [InfoAttribute("DocMaster", InfoAttribute.ClassificationType.DocMaster)]
2:
3: public class DocMasterInfo
5.若要在程式中使用屬性(Attribute),可使用System.Attribute.GetCustomAttribute的方法
1: Type t = this.GetType();
2:
3: Type tAttribute = typeof(InfoAttribute);
4:
5: _InfoAtt = System.Attribute.GetCustomAttribute(t, tAttribute) as InfoAttribute;
將它轉型成剛剛自訂的Attribute(InfoAttribute),即可在程式中使用。
使用Attribute的時機,通常是已經知道這個物件的特性,
藉由屬性設定來訂定物件的相關特性,
而不用藉由一堆程式撰寫,將這些已知的屬性設計進Class中,
在WCF裡,使用屬性方式來訂定傳輸的一些設定,透過屬性的設定之後,
就可以完成物件的設計。
PS.寫得很亂,還是先大致寫到這。
2010-05-04
WCF- Asynchronous Call
還是一樣開始慢慢練習WCF,首先就先從最常使用的Asynchronous 呼叫來練習。
非同步的呼叫,對設計Client端應用程式來說相當重要,
因為在向Service請求回應時,為了要等待Service回應,
應用程式必須要等待,萬一這段期間需要很長的處理時間,
程式就會停在那,完全無法動作
(這點再設計Client端時需要注意,因為使用者會誤認為當機)
所以,不管是Service或是在Client端執行邏輯時,
我都會將需要花很長時間才能完成的程式,
放在背景執行,並有Progress bar來顯示進度。。。
好了~廢話少說,就先來練習這個小小的課題!
要使用非同步的Method,首先先在[加入服務參考]中
選擇[進階]選項->勾選[產生非同步作業]
之後在Client端中,新增一個ServiceClient,
可以在intellisense中找到有Begin開頭與End開頭的Method,
程式碼如下:
1: SE.Service1Client se = new TestWCF1.SE.Service1Client();
2:
3: AsyncCallback ac=new AsyncCallback(MyCallBack);
4:
5: IAsyncResult iarResult = se.BeginGetData(1, ac, "Please wait...........");
6:
7: //----------------
8:
9: /*
10:
11: * 繼續執行接下來的程式
12:
13: */
14:
15: //----------------
16:
17: string strResult = se.EndGetData(iarResult);
18:
19: MessageBox.Show(strResult);
寫得比較簡陋一點 XD ,再呼叫Begin Method時,
Client端還可以同時去執行其他工作,
直到呼叫End Method後,將結果拿取回來。
這個方法對我來說很少使用,因為我比較喜愛使用訂閱事件的方式,
也就是說當結果產生時,才觸發事件通知我去拿取,
因為有可能是再呼叫End Method時,Service還未完成結果,
結果Client端就必須等在那等待Service回傳。
另一個寫法如下:
Service會產生一個有Async結尾的Method,Client端再去訂閱Completed事件,
例如:今天Service提供GetData的Method,所以會有GetDataAsync
Method與GetDataAsyncCompleted事件
1: SE.Service1Client se = new TestWCF1.SE.Service1Client();
2:
3: se.GetDataCompleted+=new EventHandler<TestWCF1.SE.GetDataCompletedEventArgs>se_GetDataCompleted);
4:
5: se.GetDataAsync(2);
之後Client再借由Completed Method取得回傳的資料。
1: void se_GetDataCompleted(object sender, TestWCF1.SE.GetDataCompletedEventArgs e)
2:
3: {
4: if (e.Cancelled){}
5: else if (e.Error != null){}
6: else
7: {
8: MessageBox.Show(e.Result);
9: }
10: }
先簡單寫到這!!!
2010-05-03
delegate 匿名方法的應用
最近在準備WCF考試也快告一個段落(畢竟5/7號就要考了,今天也已經5/4 >”<)
其實這樣匆匆的準備一個月的時間,很多部分看的都不是很懂,
或許是因為自己閱讀英文能力還不夠吧,所以看得有點吃力 >"<
最近常覺得程式開發的學習,真的是一條無止盡的路,
新的技術、新的概念、對我們這些程式設計者而言,
若不時常更新,可能隨時就被新潮流給掩沒!!
==========================================
今天來記錄一下,前陣子林大哥分享的技術。
在程式裡面,我們會常常需要使用到找尋某一個物件資料,
在.Net 2.0的時候,只要有實作IDictionay的類別都有索引鍵/值組,
也就是說將物件資料放進這個集合中,即可用Key找出相對應的物件,
這樣的物件集合對程式來說相當方便,但若遇到未實作這個介面的集合時
那又該如何呢??
舉例來說,假設今天有一個集合 List<string> ,我想要找集合中符合"AAA"的字串,
對我這樣的小嫩嫩設計師來說,可能會選擇這種寫法:
1: List<string> myList= new List<string>();
2: myList.Add("AAA");
3: myList.Add("BBB");
4: myList.Add("CCC");
5:
6: foreach (string thisString in myList)
7: {
8: if (thisString.CompareTo("AAA") == 0)
9: {
10: MessageBox.Show("找到AAA物件");
11: }
12: }
但其實還有一種更Smart的簡易寫法,
其實.Net 2.0時就有提供delegate 匿名方法寫法如下:
1: private void button1_Click(object sender, EventArgs e)
2: {
3:
4: List<string> myList= new List<string>();
5:
6: myList.Add("AAA");
7: myList.Add("BBB");
8:
9: myList.Add("CCC");
10:
11:
12: string strResult=myList.Find(delegate(string strFind) {
13:
14: return strFind.CompareTo("AAA")==0;
15: });
甚至於要將這個List集合來自訂Sort也可以,程式如下所示
1: List<string> myList= new List<string>();
2:
3: myList.Add("AAA");
4:
5: myList.Add("BBB");
6:
7: myList.Add("CCC");
8:
9:
10:
11: myList.Sort(delegate(string a, string b){
12:
13: return a.CompareTo(b);
14:
15: });
其實當然使用Linq這種簡單的功能也可以做到,反正就只是一個紀錄而以嚕。
2010-04-22
WCF-FaultException
這陣子在準備WCF的MCTS考試時,看了微軟發行的
[70-503 Microsoft .NET Framework 3.5 – Windows Communication Foundation]
這本書,說實在話,我看到後面第八章之後就有點看不下去
因為越看越模糊,完全不知道書中到底是在講些什麼??
尤其在這本書中提到FaultException的功能
並在書中寫下這樣的範例
1: [ServiceContract()]
2: public interface ICalculatorService
3: {
4: [OperationContract()]
5: [FaultContract(typeof(string))]
6: double Divide(double numerator, double denominator);
7: }
8: public class CalculatorService : ICalculatorService
9: {
10: public double Divide(double numerator, double denominator)
11: {
12: if (denominator == 0.0d)
13: {
14: string faultDetail = "You cannot divide by zero";
15: throw new FaultException<string>(faultDetail);
16: }
17: return numerator / denominator;
18: }
19: }
原本以為照這樣書中的練習,應該就可以看到結果,
結果沒想到程式出現了意外的錯誤狀況 >”<
原因是甚麼?請教Google大神之後,我還是沒有找到解答,
(一方面可能是自己找的方向不對,所以就放棄)
事情就這樣結束了嗎? 不~~~這件事情還停在我腦海中,
反正我想總有一天應該會找到解答!!
之後我放棄微軟的Training kit轉而看
Professional WCF Programming - 作者:Scott Klein
書中反而說明的比較詳細,雖然對我來說還是有很多看不大懂的部分
其中又遇到FaultException說明
書中寫的範例跟Training Kit有點不大一樣,
是在FaultContract部分,多設定了ProtectionLevel
1: [OperationContract]
2: [FaultContract(typeof(MyDefFault),ProtectionLevel=ProtectionLevel.EncryptAndSign)]
3: string GetData(int value);
程式就可以Work了,先簡單寫到這,
等我看得比較熟悉清楚後,再來補充這部分。
最近的想法
很久沒更新這裡的網誌,算是自己偷懶偷很大。。。
因為已經隔了超長的一段時間,
所以決定長話短說,簡單列幾個項目說明重新開始寫這裡網誌的理由。
1.工作上的經驗還是得有個記錄。
2.督促自己成長的動力。
3.證明自己走過了哪些路,做了哪些事情,不希望到頭來都是白工。
4.為了更長遠的目標。
----------分隔線----------------------
今年有個目標 - 希望十月底前能拿到
MCPD -Enterprise Application Developer 3.5
會有這樣的想法,或許多多少少因為現在工作的關係,
最近常在想自己,已經在程式Coding中打混了三年多的時間,
到底會了些什麼?
說實在我真的也很難說明,可是平常很努力的完成很多事情,
但到現在卻說不清楚到底做了甚麼,也都沒留下甚麼記錄!
總覺得很可惜。。。
我希望接下來的日子裡,一定要花點時間來維護這裡,
希望自己千萬不要偷懶。。。
也期望自己能多多加油才行!!