程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 使用C#輕松編寫.Net組件

使用C#輕松編寫.Net組件

編輯:關於C語言

在.net框架提出之前,編寫組件被視為是一種需要高深技巧的工作,令很多人望而生畏。而.net的出現,使得組件的編寫變得如此平易近人,而.net framework的核心語言C#,更是被稱為面向組件的語言。在這裡,我將向大家介紹如何使用C#編寫在.Net framework環境下運行的組件,包括如何編寫組件類,如何添加域、屬性以及事件,如何編譯和分發組件。
  
  
  
  
  
  
  
    首先看下面這段足夠簡單的代碼實例(在後面我們將慢慢將它變成一個五髒俱全的組件):
  
  using System;
  namespace ComponentCS
  {
  public class StringComponent
  {
  private string[] StringsSet;
  public int StringLength
  {
  get
  {
  return StringsSet.Length;
  }
  }
  public void Modify(int index,string value)
  {
  if ((index < 0) || (index >= StringsSet.Length))
  {
  throw new IndexOutOfRangeException();
  }
  else
  {
  StringsSet[index]=value;
  OnModify();
  }
  }
  public StringComponent()
  {
  StringsSet = new string[]
  {
  "C# String 0",
  "C# String 1",
  "C# String 2",
  "C# String 3"
  };
  }
  public string GetString(int index)
  {
  if ((index < 0) || (index >= StringsSet.Length))
  {
  throw new IndexOutOfRangeException();
  }
  return StringsSet[index];
  }
  }
  }

一般地,我們首先創建一個命名空間(namespace)用來封裝這個組件中一系列的類:
  
  namespace CompCS
  
    命名空間的使用非常靈活,它可以被嵌套,也可以將其內部的類分別寫在多個文件中,相應地,還可以在一個源文件中聲明多個非嵌套的命名空間。下面是一個使用嵌套的命名空間的示例代碼:
  
  namespace NestIt{ namespace NestedNameSpace { class myClass { public static void DOSth() { ... } } }}
  
    你可以這樣引用類myClass:
  
    NestIt.NestedNameSpace.myClass.DOSth();
  
    還是回到我們的命名空間CompCS,我們使用下面的語句聲明了一個類StringComponent:
  
    public class StringComponent
  
    命名空間中的類是必需的,因為C#所有的代碼都必須封裝在一個個類中,所以沒有類的命名空間沒有任何價值。
  
    下面我們為這個類添加一個公共(public)域:
  
    private string[] StringsSet;
  
    此外,它還可能需要定義一些屬性,下面是定義一個只讀的屬性的例子:
  
  public int StringLength{ get { return StringsSet.Length; }}
  
    C#中的屬性更充分地體現了對象的封裝性,不直接操作類的數據內容而是通過訪問器進行訪問,它借助於get 和set訪問器對屬性的值進行讀寫。而在C++中,這是需要程序員手工完成的一項工作。
  
    在屬性的訪問聲明中:
  
     .只有set 訪問器表明屬性的值只能進行設置而不能讀出
  
     .只有get 訪問器表明屬性的值是只讀的不能改寫
  
     .同時具有set 訪問器和get 訪問器表明屬性的值的讀寫都是允許的
  
    你或許會發現域和屬性是如此相似,確實屬性和域的語法比較類似的,但是它們是絕對不同的,區別在於你不能把屬性當做變量那樣使用,也不能把屬性作為引用型參數或輸出參數來進行傳遞,相反的,對於域,沒有這些限制。
  
    下面的代碼定義了這個類的構造函數:
  
    public StringComponent()
  
    構造函數必須與類同名,它可以重載,但是不能有返回值,因此它也沒有返回值類型前綴。當用戶新建一個類的實例時,構造函數就會自動執行,同時,C#的垃圾收集機制開始對這個實例進行管理,並且將在適當的時候回收資源。
然後,我們編寫了一個GetString()函數,這個函數根據用戶傳入的index值,返回相應的記錄:
  
  public string GetString(int index)
  { … return StringsSet[index];}
  
    要注意的是其中的異常處理的方法:
  
    throw new IndexOutOfRangeException();
  
    作為一個健壯的組件,異常處理機制是不可或缺的,雖然它可能會消耗掉一些資源,但是它帶來的安全性的提升會使你覺得消耗的資源簡直微不足道。這裡使用了一個系統定義的異常類IndexOutOfRangeException(),事實上,更多的情況是你必須自己定義異常類,以適應各種不同的情況。下面的代碼示例展示了如何定義一個異常類:
  
  public class MyApplicationException : ApplicationException{ public string AMsg;
  public MyApplicatonException(string strMsg)
  {
  AMsg=strMsg;
  }
  }
  
    定義一個異常類與定義普通的類並沒有什麼區別,唯一的區別在於異常類必須繼承自System.Exception類。事實上,微軟公司推薦把所有用戶自定義的異常類作為ApplicationException類的子類。把類MyApplicationException放到命名空間CompCS中,這樣你就可以改寫GetString()函數中的異常處理方式。下面是一個帶有更完善的異常處理機制的GetString()方法:
  
  public string GetString(int index) { try { if ((index < 0) || (index >= StringsSet.Length)) { throw new MyApplicationException("參數超出范圍"); } } catch(MyApplicationException mErr) { Console.WriteLine(mErr.AMsg); } catch(Exception Err) { Console.WriteLine(Err.Message); }
  return StringsSet[index];
  }
  
    采用類似這樣的方式,你可以應付比這復雜得多的情況。
  
    下面,我們來考慮給這個類添加事件。事件機制的引入使得開發者可以更靈活地開發程序。下面的代碼示例展示了如何定義一個事件:
  
    public event EventHandler ModifIEd;
  
    在C#中使用event關鍵字定義事件。把這個定義放到我們的類ComponentCS.StringComponent中,然後我們添加一個函數Modify(),這個函數修改字符數組StringsSet中指定位置的值,同時引發OnModify事件,而在Modify事件中,我們調用的是事件ModifIEd所指定的函數:
  
  public void Modify(int index,string value) { if ((index < 0) || (index >= StringsSet.Length)) { throw new IndexOutOfRangeException(); } else { StringsSet[index]=value; OnModify(); } }
  private void OnModify()
  {
  EventArgs e=new EventArgs();
  if(!(ModifIEd==null))
  ModifIEd(this,e);
  }
  
    然後我們可以用如下的方法調用:
  
  private void DoIt(){ StringComponent mysc=new StringComponent(); mysc.ModifIEd+=new EventHandler(Called); mysc.Modify(2,"another string");}public void Called(object o,EventArgs e){ Console.WriteLine("Changed");}
  
  
    在函數DoIt()中,我們首先建立了一個StringComponent類的對象mysc,然後將它的MofidIEd事件關聯到Called()方法:
  
    mysc.ModifIEd+=new EventHandler(Called);
  
    注意“+=”符號的使用,相反地,如果使用“-=”符號,可以取消這個事件的綁定。
  
    現在我們得到了一個雖然簡單,但是比較完整的組件類:
  
  using System;
  namespace ComponentCS
  {
  public class StringComponent
  {
  
  private string[] StringsSet;
  public event EventHandler ModifIEd;
  public int StringLength
  {
  get
  {
  return StringsSet.Length;
  }
  }
  public void Modify(int index,string value)
  {
  if ((index < 0) || (index >= StringsSet.Length))
  {
  throw new IndexOutOfRangeException();
  }
  else
  {
  StringsSet[index]=value;
  OnModify();
  }
  }
  private void OnModify()
  {
  EventArgs e=new EventArgs();
  if(!(ModifIEd==null))
  ModifIEd(this,e);
  }
  public StringComponent()
  {
  StringsSet = new string[]
  {
  "C# String 0",
  "C# String 1",
  "C# String 2",
  "C# String 3"
  };
  }
  public string GetString(int index)
  {
  if ((index < 0) || (index >= StringsSet.Length))
  {
  throw new IndexOutOfRangeException();
  }
  return StringsSet[index];
  }
  }
  }
  
  
    最後要做的就是把它編譯成.dll(動態鏈接庫)文件,以便發布。發布成.dll文件最大的好處就是.dll文件中的內容已經編譯,可以大大加快程序運行速度,此外還可以保護源代碼。
  
    將產生的.cs文件編譯成為.dll文件的方法如下:
  
    csc.exe /t:library /debug+ /out:myCom.dll example.cs
  
    這樣就輸出了名為myCom.dll的.dll文件。
  
    OK,我們已經完成一個組件,麻雀雖小,五髒俱全,這就是一切組件的基礎了,整個過程花不了十分鐘。
   當然,如果是一個具備實際使用價值的組件,我們要考慮的遠遠不止這些,但是可以看到,C#對組件的強大支持,可以大大提高我們的開發效率,從而使我們有更多的精力放在算法設計等方面,開發出更加出色的組件。 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved