2010-12-16

C# Reflection 一些雜項記錄(書中介紹之外的)

最近的程式設計中,用到滿多Reflection(反映)的做法。
以下我先簡單記錄這陣子的心得,首先先做一個範例說明:
MyLibrary-> Class library project.
WindowsFormsApplication2->Windows form project.

image 

MyLibrary.dll程式碼如下:(建立一個book class)
image

1.取得對應的
Type
一般我們取得的方式都是使用Assembly.GetTypes() 或是 Assembly.GetType(),
這些方式都是滿常用的,今天要介紹的是比較不同的。
其實在Type類別中有一個static GetType(string),這個也可以取得相對應的Type。
image 
執行結果:
image

2.取得實體物件
在這裡一般書上都會先找出
ConstructorInfo這個建構式後在去取得實體物件,如下說明:
image 
執行結果:
image 

今天要記錄的是滿少看到的用法(對我啦! XD),
Activator.CreateInstance
image
執行結果:
image
 

3.動態加入事件
這裡是使用
EventInfo Class
image

執行結果:
image
image

先簡單記錄到這,以後要補充的再加上!!

Chain Constructors

在Refactoring to Patterns一書中有提到Chain Constructors的觀念,
書中的意思是說,在不同的建構式中,出現重複的程式碼,
可以借由Chain Constructors來將複雜的程式碼簡化

譬如今天建立一個物件,其建構式如下
image
在MyEmployee的建構式中,提供了三個不同的建構式,
因為對這個MyEmployee的物件中,Telephone與Fax是可有可無的條件,
所以希望是說藉由不同的建構式,來建立適當的物件即可,

但~注意到了嗎?以上的程式碼是不是看得很礙眼?
重複的程式碼不斷的出現在建構式中,其實!!!
我們可以精簡如下:
image

看~是不是簡單多了??
在最終的建構式中,提供全部的條件需求,
其他的兩個建構式分別去呼叫最終的那個建構式,
這樣不僅是在維護上更加方便,在觀看程式碼的時候也會比較清晰。
簡單記錄下來,提供日後參考。

2010-12-09

WinForm 重構

這次因為新的功能需求,需要改寫之前所撰寫的程式功能,
Business Logic幾乎都沒變動,唯一變動的是UI畫面,
以及前端登入時的一些資料驗證功能,但這些小變更卻花了我不少時間重構。
為什麼呢?請聽我慢慢細說。。。

當初在設計這支程式的時候,是有遵循MVC的設計方式,
該是UI該做的顯示畫面,或是Model該處理的Business Logic都是有相當程度的區隔
但是卻沒有相當嚴謹的遵循,導致有些Logic還是放在UI層,
例如:Form Class裡頭竟然還有Business Logic,當我在重新修改功能的同時,
也順便將這些不該存在的東西全部抽離。

UI層就完全是在顯示資料用,他不需要管底層到底做了哪些事情,
而Model則是完全處理關於Business Logic,這樣把權責給區分出來,
這樣重構下來對以後在維護的時候會更加方便。

另外,再提到一個小觀念,其實這是之前就已經知道的事情,
但是卻還是到現在才又開始想起,我先提一段程式碼。如下所示:
image
image 
其中tbxName、tbxage是Textbox控制項,一般在寫WinForm的時候,
我在想大部分的人都應該跟我一樣,都很偷懶直接在Button的事件中寫完所有的事情,
不管是方便性來說,或是以後在維護來講其實都挺方便的(只要看這個Method就好)

但是。。。
今天若又有一個Button要提示未滿18或已滿18,
不知道你是不是也會跟我一樣這樣寫?
image
 
image
image

這樣真的可以Work,但是各位看官,您發現了嗎?
程式裡多了好幾句反覆的程式碼,這樣的寫法很不恰當,
因為萬一又多了一個Button又要做其他功能,是不是又要再寫一次轉換int的程式?
(這裡還不包括是不是會遇到不是int的錯誤)

這裡比較好的作法應該是這樣,設計成屬性
(當然若是只在這個Class中使用請將層級換成private)
這樣的好處是,程式可以重複使用,另外也可以加入驗證機制。
image 

另外寫在Button的程式碼,是不是又更簡單易懂??
image

這麼簡單的東西,我竟然現在才想到,真的是。。。
記錄下來以後可以這樣設計!!





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)供範例使用。
image
C# 1.0 委派寫法
image
image
 

C# 2.0 委派寫法
(1) Delegate新寫法
 image 
另外甚至於可以直接這樣寫-> objCollection.Find(FindObject2)即可
image

(2) Anonymous 寫法
image
image 

C#3.0 委派寫法(這部分就完全是看網頁上說明了!!)
image 可以簡化寫成如下表示
省略定義targetObj型態和return
 image

看完以上的寫法後,我在想若可以的話以後會盡量使用Lambda寫法。
簡單記錄下,提供以後參考。

2010-11-14

解決專案中不同Naming的問題

問題:
專案遇到一個滿棘手的問題,原本使用者需求希望我們產生的表單編號是(合約編號-四碼流水號)
假設合約編號是XR-332211,那所產生的表單單號為XR-332211-0001,這是原先的需求。

但是需求總是會變動的,這次使用者又覺得說這樣的表單單號太長,因為受限於一些環境需求,
而我們被迫要變動我們的程式。。。

若我們根據新需求來變動,那接下來問題又來了,若是現在這個專案是這樣,另外一個專案又需要另外的命名規則時,
我們是不是又要變動程式碼?這對我們程式設計師來說,最不希望看到的現象[不停的在修改我們的程式]。

解決方案:
跟林大哥討論完之後,他給我一個架構如下
image
我們在程式裡面針對Naming Rule設計一個合約(INaming),一個很簡單的GetName Method
image 
接下來,我們實際設計一個Naming的物件(NC6Naming),並實作INaming的GetName
image 

在這個物件中,建構式變成很重要的一個角色,
因為這裡需要別的地方提供所有可以供Naming的資料,
(此例中SpoolBaseObj有許多可以提供Naming的資料)

然後在ClientAPI中利用Reflect來操作IName取得表單命名字串。
image 
這樣若往後需要不同的專案時,可以再新增Naming的物件,
只要在ClientAPI中,告訴它要使用的是哪一個Naming物件,就可以不用到修改原始程式碼,
又能接受這樣的需求變更。

一個Class可以同時擁有兩個以上相同的Property或Method

看到這個標題,應該有很多人會感到很疑惑??

(蝦米??一個Class可以有兩個以上相同的Property或Method,怎麼可能?)

其實,若是操作Interface的話,這就不成問題

首先設計兩個不同的Interface(IA、IB),但是設計相同的屬性與Method

image 

再來設計一個Class(TestInterface),並實作IA、IB

image

接下來實際操作這個物件,但在操作的時候請轉型成IA or IB操作

這樣就可以同一物件兩個以上相同屬性的操作

image

結果

image 

這要使用在真正的設計中,其實還沒有頭緒??該用在哪?

我在想若是要使用來擴充新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;

其中GetCustomAttribute會回傳Object型態的物件,
將它轉型成剛剛自訂的Attribute(InfoAttribute),即可在程式中使用。

使用Attribute的時機,通常是已經知道這個物件的特性,
藉由屬性設定來訂定物件的相關特性,
而不用藉由一堆程式撰寫,將這些已知的屬性設計進Class中,
在WCF裡,使用屬性方式來訂定傳輸的一些設定,透過屬性的設定之後,
就可以完成物件的設計。

PS.寫得很亂,還是先大致寫到這。

2010-05-04

WCF- Asynchronous Call

還是一樣開始慢慢練習WCF,首先就先從最常使用的Asynchronous 呼叫來練習。

非同步的呼叫,對設計Client端應用程式來說相當重要,
因為在向Service請求回應時,為了要等待Service回應,
應用程式必須要等待,萬一這段期間需要很長的處理時間,
程式就會停在那,完全無法動作
(這點再設計Client端時需要注意,因為使用者會誤認為當機)

所以,不管是Service或是在Client端執行邏輯時,
我都會將需要花很長時間才能完成的程式,
放在背景執行,並有Progress bar來顯示進度。。。

好了~廢話少說,就先來練習這個小小的課題!
要使用非同步的Method,首先先在[加入服務參考]中
image
選擇[進階]選項->勾選[產生非同步作業]
image 

之後在Client端中,新增一個ServiceClient,
可以在intellisense中找到有Begin開頭與End開頭的Method,
image
程式碼如下:

   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:  }

原本以為照這樣書中的練習,應該就可以看到結果,
結果沒想到程式出現了意外的錯誤狀況 >”<

image 

原因是甚麼?請教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中打混了三年多的時間,
到底會了些什麼?
說實在我真的也很難說明,可是平常很努力的完成很多事情,
但到現在卻說不清楚到底做了甚麼,也都沒留下甚麼記錄!
總覺得很可惜。。。

我希望接下來的日子裡,一定要花點時間來維護這裡,
希望自己千萬不要偷懶。。。
也期望自己能多多加油才行!!