.NET

Microsoft XML Web services 平台

.NET 是 Microsoft XML Web services 平台。XML Web services 允許應用程序通過 Internet 進行通訊和共享數據,而不管所採用的是哪種操作系統、設備或編程語言。Microsoft .NET 平台提供創建 XML Web services 並將這些服務集成在一起之所需。

2014年4月4日,微軟成立.NET基金會去管理和引導開源組件的開發;2014年11月13日,微軟宣布將免費提供Visual Studio Community 2013。

概要


.net
.net
.NET就是微軟用來實現XML,Web Services,SOA(面向服務的體系結構service-oriented architecture)和敏捷性的技術。
.NET也可以如下來定義:.NET是微軟的新一代技術平台,為敏捷商務構建互聯互通的應用系統,這些系統是基於標準的,聯通的,適應變化的,穩定的和高性能的。
從技術的角度,一個.NET應用是一個運行於.NET Framework之上的應用程序。(更精確的說,一個.NET應用是一個使用.NET Framework類庫來編寫,並運行於公共語言運行時Common Language Runtime之上的應用程序。)如果一個應用程序跟.NET Framework無關,它就不能叫做.NET程序。比如,僅僅使用了XML並不就是.NET應用,僅僅使用SOAP SDK調用一個Web Service也不是.NET應用。.NET是基於Windows操作系統運行的操作平台,應用於網際網路的分散式。

開源


微軟在Build開發者大會上宣布開源一批.NET庫和相關技術,成立.NET基金會去管理和引導開源組件的開發。微軟還將在Apache 2.0許可證下開源Roslyn編譯器堆棧,Roslyn是微軟所謂的編譯器即服務,包含了C#和 Visual Basic.NET 編譯器。.NET基金會由來自微軟、GitHub和Xamarin的代表組成,Xamarin由GNOME創始人Miguel de Icaza等人創建,開發.NET開源實現。Xamarin向基金會貢獻了它的部分庫。de Icaza在接受採訪時表示,微軟已經變了,不僅僅移除了許可證中的限制,而且與Xamarin合作徵求設計反饋,在創作共用許可證下發布文檔。
2014年4月的Build開發者大會上,微軟宣布開源一批.NET庫和相關技術,成立.NET基金會去管理和引導開源組件的開發。微軟還將在Apache 2.0許可證下開源Roslyn編譯器堆棧,Roslyn是微軟所謂的編譯器即服務,包含了C#和 Visual Basic.NET 編譯器。.NET基金會由來自微軟、GitHub和Xamarin的代表組成,Xamarin由GNOME創始人Miguel de Icaza等人創建,開發.NET開源實現。Xamarin向基金會貢獻了它的部分庫。de Icaza在接受採訪時表示,微軟已經變了,不僅僅移除了許可證中的限制,而且與Xamarin合作徵求設計反饋,在創作共用許可證下發布文檔。
2014年11月13日,為了進一步擴大雲計算市場,微軟將不再把.NET和Visual Studio等關鍵軟體技術局限在Windows平台,今後還將兼容Linux、Mac OS X、iOS和Android。除此之外,微軟還宣布將開放.NET核心伺服器運行環境和框架的源代碼,使得外部開發者也可以對這一軟體開發平台做出貢獻。
2014年11月14日,宣布將免費提供Visual Studio Community 2013,作為這一變化的一部分,微軟將允許開發者使用.NET運行環境和框架,來為Linux和Mac開發基於伺服器和雲端的應用。並將免費對獨立開發者、學生、小企業等用戶開放。

域名


.net是國際最廣泛流行的通用域名格式。一般用於從事Internet相關的網路服務的機構或公司,是建立全球商業品牌,國際化形象的第一選擇。

應用組件


客戶端應用

組成.net軟體技術的組件,組件之一,“智能”客戶端應用軟體和操作系統,包括PC、PA、手機或其他移動設備通過網際網路、藉助Web Services技術,用戶能夠在任何時間、任何地點都可以得到需要的信息和服務。例如:可以在手機上閱讀新聞、定購機票、瀏覽在線相冊等等。CRM系統,應用了.NET的解決方案后所有的業務人員便可以通過手機或PDA直接訪問客戶信息了。WebServices
Web Services是智能終端軟體的基礎,微軟為用戶創建智能終端提供了一整套豐富的解決方案,包括:
.NET Framework- 智能終端實現跨平台(設備無關性)的
Visual Studio .NET – 建立並集成Web Services和應用程序的快速開發工具
Microsoft Windows Server 2003 – 新一代的企業伺服器,用於提供建立和發布各種解決方案
Microsoft Office Professional Edition 2003 – 內建的工具集也能幫助開發智能終端
.net
Web Services是.NET的核心技術。那什麼是Web Services呢?正如Web是新一代的用戶與應用交互的途徑,XML是新一代的程序之間通訊的途徑一樣,Web Services是新一代的計算機與計算機之間一種通用的數據傳輸格式,可讓不同運算系統更容易進行數據交換。Web Services有以下幾點特性:Web services允許應用之間共享數據;Web services分散了代碼單元;基於XML這種internet數據交換的通用語言,實現了跨平台、跨操作系統、跨語言。那微軟的ASP和Web services究竟有什麼不同呢,ASP仍然是一個集中式計算模型的產物,只不過是披著一層網際網路的外衣。但Web Services卻是一個迥然不同的精靈,它秉承“軟體就是服務”的真言,同時順應分散式計算模式的潮流。而它的存在形式又與以往軟體不同。這種組件模式,小巧、單一,對於開發人員來講,開發成本較低。
在這裡指出Web services不是微軟發明的,同樣也不屬於微軟專有。Web services是一個開放的標準,和HTTP、 XML、SOAP一樣。他們是一個工業標準而非微軟標準,WS-I是為了促進Web Services互通性的聯盟組織,最初是由IBM和微軟所發起,其它的成員包括BEA System、惠普計算機(HP)、甲骨文(Oracle)、英特爾(Intel)和SUN 計算機(Sun Microsystem)。如今網路上存在的大多Web services其實沒有使用.NET構架,Web services具有互操作屬性,你同樣可以使用Windows開發客戶端來調用運行於Linux上面的Web services的方法。

介面規範

.net
.net
提到的介面規範問題,在.NET中,Web service介面通常使用Web Services Description Language (WSDL)描述。WSDL 使用XML來定義這種介面操作標準及輸入輸出參數,看起來很像COM和CORBA的介面定義語言(IDLS)Interface Definition Languages。介面定義后就必須使用一些協議調用介面,如SOAP協議,SOAP源於一種叫做XML RPC(XML遠程進程調用remote procedure calling)的協議,而Java則根據XML-RPC發展了自己的JAX-RPC協議用來調用Web Services。發布和訪問Web Services的介面就用到UDDI了,這裡我們只需要知道WSDL使用XML定義Web Services介面,通過SOAP訪問Web Services,在internet上尋找Web Services使用UDDI就行了。伺服器架構——Microsoft Windows Server System Microsoft提供了最佳的伺服器構架—Microsoft Windows Server System—便於發布、配置、管理、編排Web Services。為了滿足分散式計算的需要微軟構造了一系列的伺服器系統,這些內建安全技術的系統全部支持XML,這樣加速了系統、應用程序以及同樣使用Web Services的夥伴應用之間的集成。
Microsoft Windows Server System包括:
Microsoft Application Center 2000 - 配置和管理Web應用程序
Microsoft BizTalk Server 2002 - 建立基於XML的跨應用和組織的商業邏輯
visual studio .net
Microsoft Commerce Server 2002 – 能夠迅速建立大規模電子商務的解決方案
Microsoft Content Management Server 2002 – 管理動態電子商務網站的目錄
Microsoft Exchange Server 2000 – 用於進行隨時隨地的通訊協作
Microsoft Host Integration Server 2000 – 用於和主機系統之間傳輸數據
Microsoft Internet Security and Acceleration Server 2000 (ISA Server) – internet連接
Microsoft Mobile Information Server 2002 – 用於支持手持設備
Microsoft Operations Manager 2000 – 描述企業級解決方案的操作管理
Microsoft Project Server 2002 - 提供項目管理的最佳方案
Microsoft SharePoint Portal Server 2001 – 查詢、共享、發布商業信息
Microsoft SQL Server 2000 – 企業級資料庫
Microsoft Visual Studio .NET和Microsoft .NET Framework對於建立,發布並運行Web Services是一個完美的解決方案。

CLR與CIL

.NET的
NET Framework 環境
初級組成是CIL和CLR。CIL是一套運作環境說明,包括一般系統、基礎類庫和與機器無關的中間代碼,全稱為通用中間語言(CIL)。CLR則是確認操作密碼符合CIL的平台。在CIL執行前,CLR必須將指令及時編譯轉換成原始機械碼。
所有CIL(通用中間語言)都可經由.NET自我表述。CLR檢查元資料以確保正確的方法被調用。元資料通常是由語言編譯器生成的,但開發人員也可以通過使用客戶屬性創建他們自己的元資料。
如果一種語言實現生成了CIL,它也可以通過使用CLR被調用,這樣它就可以與任何其他.NET語言生成的資料相交互。CLR也被設計為作業系統無關性。
當一個彙編體被載入時,CLR執行各種各樣的測試。其中的兩個測試是確認與核查。在確認的時候,CLR檢查彙編體是否包含有效的元資料和CIL,並且檢查內部表的正確性。核查則不那麼精確。核查機制檢查代碼是否會執行一些“不安全”的操作。核查所使用的演演演算法非常保守,導致有時一些“安全”的代碼也通不過核查。不安全的代碼只有在彙編體擁有“跳過核查”許可的情況下才會被執行,通常這意味著代碼是安裝在本機上的。
通過.NET,你可以用SOAP和不同的Web services進行交互。

依賴關係


每個新版本的 .NET Framework 都會保留早期版本中的功能並會添加新功能。 CLR 由其自己的版本號確定的。某些版本的 .NET Framework 包含新版本的 CLR,而其他版本的 .NET Framework 使用早期版本的 CLR。例如,.NET Framework 4 包含 CLR 4,而 .NET Framework 3.5 包含 CLR 2.0。 (沒有版本 3 的 CLR。)雖然 .NET Framework 4.5 是 .NET Framework 4 的就地更新,基礎 CLR 版本號成為 CLR 4.5。
通常,您不應卸載計算機上安裝 .NET Framework 的任何版本,因為您使用的應用程序可能取決於特定版本,並且可能中斷,如果移除該版本。您可以同時在一台計算機上載入 .NET Framework 的多個版本。這意味著可以安裝 .NET Framework,而無需卸載舊版本。

2.0版本


完整版號 - 2.0.50727.42,發佈於2005年10月27日。
.NET框架 2.0的組件都包含在 Visual Studio 2005和SQL Server 2005裡面。通過MSDN Universe版可以免費下載RTM版本。
自1.1版本以來的改進:
大量的API變更。
新的API讓需要管理.NET運行庫實例的非.NET的應用程序可以做到這點。這個新的API對.NET運行庫的各種功能,包括:多線程、存儲器分配、代碼載入等,提供了很好的控制。它最初是為Microsoft SQL Server能夠有效率的使用.NET運行庫而設計的,因為Microsoft SQL Server擁有它自己的日程管理器和存儲器管理器。

4.5版本


.NET框架 4.5 是 .NET框架 4 高兼容性的就地更新 (in-place update)。搭配 C# 或 Visual Basic 程序設計語言使用 .NET框架 4.5,即可編寫 Windows Store 風格的應用程序。 .NET框架 4.5 可提升性能、可靠度及安全性。於2012年8月15日推出。但請注意,.NET框架 4.5不支持Windows XP操作系統。

4.0版本


.NET Framework 4.0,英文版於2010年4月12日推出。
主要的新特性有以下幾個方面:
動態編程
并行計算
後期綁定
協變與逆變
接下來我們一一領略C# 4.0中的語言特性。

動態編程


C#是靜態強類型語言。而在很多情況下,提供“動態”行為,是常常發生的事情,例如通過反射在運行時訪問.NET類型、調用動態語言對象、訪問COM對象等,都無法以靜態類型來獲取。因此, C# 4.0引入的又一個全新的關鍵字dynamic,也同時引入了改善靜態類型與動態對象的交互能力,這就是動態查找(Dynamic Lookup)例如:
public static void Main() {
dynamic d = GetDynamicObject();
d.MyMethod(22); // 方法調用
d.A = d.B; // 屬性賦值
d[“one”] = d[“two”]; //索引器賦值
int i = d + 100; // 運算符調用
string s = d(1,2); // 委託調用
}
就像一個object可以代表任何類型,dynamic使得類型決斷在運行時進行,方法調用、屬性訪問、委託調用都可動態分派。同時,動態特性還體現在構建一個動態對象,在C# 4.0實現IDynamicObject介面的類型,可以完全定義動態操作的意義,通過將C#編譯器作為運行時組件來完成由靜態編譯器延遲的操作,例如:
dynamic d = new Foo();
string s;
d.MyMethod(s,3,null);
在具體執行過程中,C#的運行時綁定器基於運行時信息,通過反射獲取d的實際類型Foo,然後在Foo類型上就MyMethod方法進行方法查找和重載解析,並執行調用,這正是動態調用的背後秘密:DLR。在.NET 4.0中將引入重要的底層組件DLR(Dynamic Language Runtime,動態語言運行時),除了實現動態查找的基礎支持,DLR也同時作為基礎設施為類似於IronRuby、IronPython這樣的動態語言提供統一的互操作機制。總而言之,動態編程將為C#在以下領域產生巨大的變革:
· Office編程與其他COM交互。
·動態語言支持,在C#中消費IronRuby動態語言類型將並非難事,體驗動態語言特性指日可待。
· 增強反射支持。
以調用IronRython為例,我們只需引入IronPython.dll,IronPython.Modules.dll,and Microsoft.Scripting.dll,即可通過創建ScriptRuntime在C#中HostingIronPython環境,進而來操作動態語言的類型信息。
ScriptRuntime py = Python.CreateRuntime();
dynamic mypy = py.UseFile("myfile .py");
Console.WriteLine(mypy.MyMethod("Hello"));
雖然從微軟當前提供的技術資料和CTP演示中,動態查找還存在或多或少的問題,但是在“動態”大行其道的今天,我們無法迴避也必須擁抱這個未來的主角,因為我堅信明天會更好。

并行計算


.net
.net
并行計算的出現,是計算機科學發展的必然結果,隨著計算機硬體的迅猛發展,在多核處理器上工作已經是既存事實,而傳統的編程模式必須兼容新的硬體環境才能使計算機性能達到合理的應用效果。用Anders大師的話說:未來5到10年,并行計算將成為主流編程語言不可忽視的方向,而4.0為C#打響了實現併發的第一槍。
未來的.NET Framework 4.0中將集成TPL(Task Parallel Library)和PLINQ(Parallel LINQ),這也意味著未來我們可以應用C# 4.0實現并行化應用,在統一的工作調度程序下進行硬體的并行協調,這將大大提高應用程序的性能同時降低現存併發模型的複雜性。
那麼,我們應該一睹為快應用C#武器來開發併發環境下的超酷感受,在System.Threading.Parallel 靜態類提供了三個重要的方法For、Foreach、Invoke可以為我們小試牛刀:
//應用TPL,執行并行循環任務
Parallel.For(0,10,i =>{DoSomething(i);});
在線程爭用執行情況下,相同的操作在雙核平台下運行,以StopWatch進行精確時間測試,并行環境下的執行時間為 2001ms,而非并行環境下的執行時間為4500ms,并行運算的魅力果然名不虛傳。我們再接再厲應用PLINQ執行對於并行運算的查詢、排序等,當前PLINQ支持兩種方式ParallelEnumerable類和ParallelQuery類,例如:
int[] data = new int[] { 0,1,2,3,4,5,6,7,8,9 };
int[] selected = (from x in data.AsParallel()
select x + 1).ToArray();
更詳細的對比示例留待讀者在實踐中對此進行討論,并行計算為託管代碼在多核環境下的性能優化提供了統一的解決方案,而未來我們會做的更好。
備註:實際上,我們可以選擇下載安裝Microsoft Parallel Extensions to the .NET Framework 3.5June 2008 CTP包,就可以在.NET 3.5環境下體驗并行計算的無窮魅力。

協變和逆變


協變和逆變,是為解決問題而生的。而要理清解決什麼樣的問題,需要首先從理清幾個簡單的概念開始。首先我們進行一點操作:
Derived d = new Derived();
Base b = d;
Derived類型繼承自Based類型,由Derived引用可以安全的轉換為Based引用,而這種轉換能力可以無縫的實現在Derived數組和Base數組,例如:
Derived[] ds = new Derived;
Base[] bs = ds;
而這種原始轉換(由子類轉換為父類)方向相同的可變性,被稱為協變(covariant);其反向操作則被稱為逆變(contravariant)。當同樣的情形應用於泛型時,例如:
List ds = new List();
List bs = ds;
類似的操作卻是行不通的。所以,這就成為C# 4.0中完善的問題——泛型的協變與逆變:
List bs = new List(); List ds = new List();
bs = ds; //List;支持對T協變
ds = bs; //List;支持對T逆變
而在C# 4.0中,伴隨著協變與逆變特性的加入,C#引入兩個in和out關鍵字來解決問題。
public interface ICovariant {
T MyAction();
}
public interface IContravariant
{
void MyAction(T arg);
}
其中,out表示僅能作為返回值的類型參數,而in表示僅能作為參數的類型參數,不過一個介面可以既有out又有in,因此既可以支持協變、支持逆變,也可以同時支持,例如:
public interface IBoth
{
}

默認參數


.net
.net
命名參數和可選參數是兩個比較簡單的特性,對於熟悉其他編程語言的開發者來說可選參數並不陌生,為參數提供默認值時就是可選參數:
public void MyMethod(int x,int y = 10,int z = 100) {
}
因此,我們可以通過調用MyMethod(1)、MyMethod(1,2)方式來調用MyMethod方法。而命名參數解決的是傳遞實參時,避免因為省去默認參數造成的重載問題,例如省去第二個參數y調用時,即可通過聲明參數名稱的方式來傳遞:
MyMethod(20,z: 200);
相當於調用MyMethod(20,10,200),非常類似於Attribute的調用方式。雖然只是小技巧,但也同時改善了方法重載的靈活性和適配性,體現了C#語言日趨完美的發展軌跡。
當然,除此之外.NET 4.0還增加了很多值得期待的平台特性,也將為C#編碼帶來前所未有的新體驗。
以上相關版權歸作者。

3.0版本


.NET Framework 3.0(曾用名WinFX)是微軟為操作系統Windows Vista(舊稱“Longhorn”)而特別設計的API。.NET Framework是對.NET架構和Win32 API的擴展。雖然Win32 API仍然存在於Windows Vista中,但是在WinFX中不能通過它直接調用。另外,WinFX將提供給.NET程序員更加簡便地方式來調用Windows中的功能。
.NET Framework 3.0同樣能在Windows XP和Windows Server 2003的計算機上運行,這樣增加了能夠運行.NET Framework 3.0程序的計算機數量。由於向後兼容,能夠更加容易將這些技術介紹給開發人員和最終用戶。2006年9月1日,微軟發布了.NET Framework 3.0的RC版本,開發人員能夠無需安裝Vista就可以體驗這些新的技術。
.NET Framework 3.0並沒有新版本的CLR,而是在.NET Framework 2.0的基礎上增加了幾個新的部件,所以並沒有任何程序設計語言有新的語法特性,如果要安裝.NET Framework 3.0,則必須先安裝.NET Framework 2.0,.NET Framework 3.0可以完全向下兼容.NET Framework 2.0。
.NET Framework 3.0主要由的四部分組成:
WPF(Windows Presentation Foundation),內部代碼“Avalon”,是一套基於XAML(eXtensible Application Markup Language)、.NET和矢量圖技術的全新的圖形界面系統和API,它充分利用了計算機的3D顯卡硬體功能和Direct3D技術。
WCF(Windows Communication Foundation),內部代碼“Indigo”,是一個面向服務的通訊框架,利用它可以實現本地和遠程的程序之間的交互。
WF(Workflow Foundation)於2005年8月公開,微軟提供的工作流引擎,通過它可以實現任務的自動化和事務的集成。
InfoCard是一個軟體組件的代碼,用來安全的保存和使用用戶的數字身份,並提供統一的界面來針對特定的事務選擇身份,例如登陸一個網站。

3.0特性


類型化變數
這個特性非常簡單,有些JavaScript的影子,我們可以統一使用使用"var"關鍵字來聲明局部變數,而不再需要指明變數的確切類型了,變數的確切類型可通過聲明變數時的初始值推斷出來。這樣一來,可以大大簡化我們聲明局部變數的工作量了,下面是一個例子:
class LocalVariables : AppRunner.AbstractApplication
{
public override void Run()
{
var intValue = 5;
var stringValue = "This is a string";
var customClass = new LocalVariables();
var intArray = new int{ 1,2,3 };
foreach (var value in intArray)
Console.WriteLine(value);
}
}
上面的代碼將被解析成:
class LocalVariables : AppRunner.AbstractApplication
{
public override void Run()
{
int intValue = 5;
string stringValue = "This is a string";
LocalVariables customClass = new LocalVariables();
int[] intArray = new int;
foreach (int value in intArray)
Console.WriteLine(value);
}
}
要特別注意的是,由於變數的類型是通過變數初始值推斷而來的,所以在聲明變數的同時必需為變數指定初始值。並且,變數並不是沒有類型的,變數一旦初始化之後,類型就確定下來了,以後就只能存儲某種類型的值了,比如上面的stringValue的類型經推斷為string,所以該變數就只能保存string類型的值了。

匿名類型


有些時候我們需要臨時保存一些運算的中間結果,特別是當這些中間結果是由多個部份組成時,我們常常會去聲明一個新的類型,以方便保存這些中間結果。表面上看起來這很正常,而細想之後就會發現,這個新類型只服務於這個函數,其它地方都不會再使用它了,就為這一個函數而去定義一個新的類型,確實有些麻煩。
C#3.0中的匿名類型特性就可以很好的解決上面提到的問題,通過匿名類型,我們可以簡單使用new { 屬性名1=值1,屬性名2=值2,.....,屬性名n=值n }的形式直接在函數中創建新的類型,看下面這個例子:
class AnonymousType : AppRunner.AbstractApplication
{
public override void Run()
{
var anonymousType1 = new {
CardNumber = "10001",Name = "van’s",Sex = true
};
Console.WriteLine(anonymousType1.CardNumber);
Console.WriteLine(anonymousType1.Name);
var anonymousType2 = new {
CardNumber = "10002",Name = "martin",Sex = true
};
anonymousType2 = anonymousType1;
}
}
在新類型中只能有欄位成員,而且這些欄位的類型也是通過初值的類型推斷出來的。如果在聲明新的匿名類型時,新類型的欄位名、順序以及初始值的類型是一致的,那麼將會產生相同的匿名類型,所以上例中anonymousType1和anonymousType2的類型是相同的,自然能進行anonymousType2=anonymousType1的賦值。
類型化數組
這個特性是對隱式類型化本地變數的擴展,有了這個特性,將使我們創建數組的工作變得簡單。我們可以直接使用"new[]"關鍵字來聲明數組,後面跟上數組的初始值列表。在這裡,我們並沒有直接指定數組的類型,數組的類型是由初始化列表推斷出來的。
class AnonymousTypeArray : AppRunner.AbstractApplication
{
public override void Run()
{
var intArray = new[] { 1,2,3,4,5 };
var doubleArray = new[] { 3.14,1.414 };
var anonymousTypeArray = new[] {
new { Name="van’s",Sex=false,Arg=22 },
new { Name="martin",Sex=true,Arg=23 }
};
Console.WriteLine(intArray);
Console.WriteLine(doubleArray);
Console.WriteLine(anonymousTypeArray[0].Name);
}
}
上面的代碼中,anonymousTypeArray變數的聲明同時運用了隱式類型化數組和匿名類型兩種特性,首先創建匿名類型,然後再初始值列表,推斷出數組的確切類型。

對象構造者


我們在聲明數組時,可以同時對其進行初始化,這樣就省去了很多麻煩,但是在創建類的對象時,這招可就不靈了,我們要麼調用該類的構造函數完成對象的初始化,要麼就手工進行初始化。這兩種方法都不太方便,使用構造函數來對對象進行初始化時,我們為了某種靈活性,可能需要編寫構造函數的多個重載版本,實在是麻煩。
C#3.0中加入的對象構造者特性,使得對象的初始化工作變得格外簡單,我們可以採用類似於數組初始化的方式來初始化類的對象,方法就是直接在創建類對象的表達式後面跟上類成員的初始化代碼。具體示例如下:
class Point
{
public int X { get; set; }
public int Y { get; set; }
public override string ToString()
{
return "(" + X.ToString() + "," + Y.ToString() + ")";
}
}
class Rectangle
{
public Point P1 { get; set; }
public Point P2 { get; set; }
public Rectangle()
{
P1 = new Point();
P2 = new Point();
}
public override string ToString()
{
return "P1: " + P1 + ",P2: " + P2;
}
}
class ObjectBuilder : AppRunner.AbstractApplication
{
public override void Run()
{
Point thePoint = new Point() { X = 1,Y = 2 };
Console.WriteLine("Point(X,Y) = ",thePoint);
Rectangle theRectangle = new Rectangle() {
P1 = { X = 1,Y = 1 },P2 = { X = 100,Y = 200 }
};
Console.WriteLine(theRectangle);
}
}
我們在定義Point類的X和Y屬性時,只須寫上該屬性的get和set訪問器聲明,C#編譯器會自動為我們生成默認的get和set操作代碼,當我們需要定義簡單屬性時,這個特性非常有用。
我們以new Point() { X = 1,Y = 2 }語句,輕鬆的完成了對Point類的初始化工作。在創建類的對象時,我們可以按照需要去初始化類的對象,只要在類的創建表達式後跟上要初始化屬性的列表即可,且可以只對需要初始化的屬性賦初值,而無需把所有屬性的初始值都寫上去。
在theRectangle對象的初始化表達式中,我們首先對P1屬性進行初始化,然而P1屬性也是一個自定義的類型,所以P1屬性的初始化是另一個類型(Point)的初始化表達式,我們可以這樣的方式來對更加複雜的類型進行初始化。
上篇文章中介紹了C# 3.0中比較簡單的四個特性,分別是隱式類型化本地變數、匿名類型、隱式類型化數組,以及對象構造者,下面我將對C# 3.0中的較複雜,同時也是非常強大的幾個特性進行介紹,供大家快速瀏覽。

集合構造者


我們可以在聲明數組的同時,為其指定初始值,方法是直接在數組聲明的後面跟上初始值列表。這樣就使數組的初始化工作變得簡單,而對於我們自己創建的集合類型,就無法享受到與普通數組一樣的待遇了,我們無法在創建自定義集合對象的同時,使用數組的初始化語法為其指定初始值。
C# 3.0中加入的集合構造者特性,可使我們享受到與普通數組一樣的待遇,從而在創建集合對象的同時為其指定初始值。為了做到這一點,我們需要讓我們的集合實現ICollection;介面,在這個介面中,完成初始化操作的關鍵在於Add函數,當我使用初始化語法為集合指定初始值時,C#編譯器將自動調用ICollection;中的Add函數將初始列表中的所有元素加入到集合中,以完成集合的初始化操作。使用示例如下:
class CollectionInitializer : AppRunner.AbstractApplication
{
class StringCollection : ICollection
{
public void Add(string item)
{
Console.WriteLine(item);
}
// Other ICollection Members
}
public override void Run()
{
StringCollection strings = new StringCollection() { "Van's","Brog","Vicky" };
}
}
在這個示例中,編譯器會自動為strings對象調用Add方法,以將初始值列表中的所有元素加入到集合中,這裡我們只是簡單將初始值列表中的元素輸出到控制台。
Lambda表達式
C# 2.0中加入的匿名代理,簡化了我們編寫事件處理函數的工作,使我們不再需要單獨聲明一個函數來與事件綁定,只需要使用delegate關鍵字在線編寫事件處理代碼。
而C# 3.0則更進一步,通過Lambda表達式,我們可以一種更為簡潔方式編寫事件處理代碼,新的Lambda事件處理代碼看上去就像一個計算表達式,它使用"=>"符號來連接事件參數和事件處理代碼。我可以這樣寫:SomeEvent += 事件參數 => 事件處理代碼;下面是完整的示例:
delegate T AddDelegate(T a,T b);
class LambdaExpression : AppRunner.AbstractApplication
{
public static event EventHandler MyEvent;
public override void Run()
{
MyEvent += delegate(object s,EventArgs e)
{
Console.WriteLine(s);
};
MyEvent += (s,e) => { Console.WriteLine(s); };
MyEvent(this,null);
AddDelegate add = (a,b) => a + b;
Console.WriteLine(add("Lambda","Expression"));
}
}
在上面的例子中,分別使用了匿名代理和Lambda表達式來實現同樣的功能,可以明顯看出Lambda表達式的實現更為簡潔。我們在使用Lambda表達式編寫事件處理代碼時,無需指明事件參數的類型,且返回值就是最後一條語句的執行結果。
擴展方法
當我們需要對已有類的功能進行擴展時,我們通常會想到繼承,繼承已有類,然後為其加入新的行為。而C# 3.0中加入的擴展方法特性,則提供了另一種實現功能擴展的方式,我們可以在不使用繼承的前提下實現對已有類本身的擴展,這種方法並不會產生新的類型,而是採用向已有類中加入新方法的方式來完成功能擴展。
在對已有類進行擴展時,我們需將所有擴展方法都寫在一個靜態類中,這個靜態類就相當於存放擴展方法的容器,所有的擴展方法都可以寫在這裡面。而且擴展方法採用一種全新的聲明方式:public static 返回類型 擴展方法名(this 要擴展的類型 sourceObj [,擴展方法參數列表]),與普通方法聲明方式不同,擴展方法的第一個參數以this關鍵字開始,後跟被擴展的類型名,然後才是真正的參數列表。下面是使用示例:
static class Extensions
{
public static int ToInt32(this string source)
{
return Int32.Parse(source);
}
public static T[] Slice(this T[] source,int index,int count)
{
if (index < 0 || count < 0 || index + count > source.Length)
{
throw new ArgumentException();
}
T[] result = new T[count];
Array.Copy(source,index,result,0,count);
return result;
}
}
class ExtensionMethods : AppRunner.AbstractApplication
{
public override void Run()
{
string number = "123";
Console.WriteLine(number.ToInt32());
int[] intArray = new int[] { 1,2,3 };
intArray = intArray.Slice(1,2);
foreach (var i in intArray)
Console.WriteLine(i);
}
}
在上面的示例中,靜態的Extensions類中有兩個擴展方法,第一個方法是對string類的擴展,它為string類加入了名為ToInt32的方法,該方法沒有參數,並返回一個int類型的值,它將完成數字字元向整數的轉換。有了這個擴展方法之後,就可對任意string類的對象調用ToInt32方法了,該方法就像其本身定義的一樣。
第二個擴展方法是一個范型方法,它是對所有數組類型的擴展,該方法完成數組的切片操作。
C# 3.0中的Linq表達式,就是大量運用擴展方法來實現數據查詢的。
Linq表達式
C# 3.0中加入的最為複雜的特性就是Linq查詢表達式了,這使我們可直接採用類似於SQL的語法對集合進行查詢,這就使我們可以享受到關係數據查詢的強大功能。
Linq查詢表達式是建立在多種C# 3.0的新特性之上的,這也是我為什麼最後才介紹Linq的原因。下面看一個例子:
class LinqExpression : AppRunner.AbstractApplication
{
public override void Run()
{
// 定義匿名數組persons,並為其賦初值
var persons = new[] {
new { Name="Van's",Sex=false,Age=22 },
new { Name="Martin",Sex=true,Age=30 },
new { Name="Jerry",Sex=false,Age=24 },
new { Name="Brog",Sex=false,Age=25 },
new { Name="Vicky",Sex=true,Age=20 }
};
var results = from p in persons
where p.Age <= 24
select p;
foreach (var person in results)
{
Console.WriteLine(person .Name);
}
Console.WriteLine();
// 定義匿名數組customers,並為其賦初值
// 該數組是匿名類型的
var customers = new[] {
new {
Name="Van's",City="China",Orders=new[] {
new {
OrderNo=0,
OrderName="C# Programming Language(Second Edition)",
OrderDate=new DateTime(2007,9,5)
},
new {
OrderNo=1,
OrderName="Head First Design Patterns(Chinese Edition)",
OrderDate=new DateTime(2007,9,15)
},
new {
OrderNo=2,
OrderName="asp .net Unleashed 2.0(Chinese Edition)",
OrderDate=new DateTime(2007,09,18)
},
new {
OrderNo=3,
OrderName="The C++ Programming Langauge(Special Edition)",
OrderDate=new DateTime(2002,9,20)
}
}
},
new {
Name="Brog",City="China",Orders=new[] {
new {
OrderNo=0,
OrderName="C# Programming Language(Second Edition)",
OrderDate=new DateTime(2007,9,15)
}
}
},
new {
Name="Vicky",City="London",Orders=new[] {
new { OrderNo=0,
OrderName="C++ Programming Language(Special Edition)",
OrderDate=new DateTime(2007,9,20)
}
}
}
};
var someCustomers = from c in customers
where c.City == "China"
from o in c.Orders
where o.OrderDate.Year >= 2007
select new { c .Name,o.OrderNo,o.OrderDate,o.OrderName };
foreach (var customer in someCustomers)
{
Console.WriteLine(
customer .Name + "," + customer.OrderName + "," +
customer.OrderDate.ToString("D")
);
}
}
}
從上面的例子中,我們可以看到Linq查詢的強大特性,它允許我們進行簡單查詢,或者進行更為複雜的多重連接查詢。且查詢的結果還可以是自定義的匿名類型。

3.5特性


快速指南
VS 2008的多定向支持
VS 2008允許你構建針對多個.NET框架版本的應用。你可以從下面的博客貼子里進一步了解其中的工作原理:
VS 2008 Multi-Targeting Su ort
VS 2008 Web設計器和C 支持
VS 2008包含一個顯著改進的HTML web設計器。該設計器提供了分割視圖編輯,嵌套母板頁,以及出色的C 集成。
A .NET還提供了一個新的控制項,該控制項對數據UI場景提供了非常靈活的支持,允許對輸出的標識做完全的定製,與VS 2008中的新C 支持還有良好的協作。
A .NET AJAX和JavaScript支持
.NET 3.5 內置提供A .NET AJAX,還添加了支持We art的UpdatePanel,支持JSON的WCF,以及N個缺陷修補和性能改進等方面的新特性。VS 2008還對集成JavaScript和AJAX進你的應用提供了極棒的支持:
VS 2008 JavaScript Intellise e
VS 2008 JavaScript Debugging
改進和LINQ
VS 2008中的新VB和C#編譯器對這些語言做了顯著的改進。兩者都添加了函數式編程概念的支持,允許你編寫更乾淨,更簡潔,更具有表達性的代碼。這些特性還促成了我們稱之為LINQ(語言級集成查詢)的新編程模型,使得查詢和操作數據成為.NET中的一等編程概念。
下面是我撰寫的一些討論這些新語言特性的文章(用C#作為示例):
自動屬性,對象初始化器,和集合初始化器
擴展方法
Lambda表達式
查詢句法
匿名類型
LINQ to SQL中的數據訪問改進
LINQ to SQL是.NET 3.5中內置的OR/M (對象關係映射器)。它允許你使用.NET 對象模型對關係資料庫進行建模。然後你可以使用LINQ對資料庫進行查詢,以及更新、插入,刪除數據。LINQ to SQL完整支持事務,視圖和存儲過程。它還提供了一個把業務邏輯和驗證規則結合進你的數據模型的簡易方式。下面是一些我討論如何使用LINQ to SQL的文章:
Part 1: Introduction to LINQ to SQL
Part 2: Defining our Data Model Cla es
Part 3: Querying our Database
Part 4: Updating our Database
Part 5: Binding UI using the A :LinqDataSource Control
我會在以後的幾周內再往這個系列里添加幾篇文章。我認為你會發現LINQ to SQL顯著地簡化了構建非常乾淨的數據模型以及編寫極其乾淨的數據代碼。
其他改進
上面的列表只是所做改進的一小部分。針對客戶端開發,VS 2008 包含了WPF設計器和項目支持。ClickOnce 和WPF XBA 在FireFox中也工作了。WinForms和WPF項目也能使用A .NET 應用服務(成員,角色和用戶數據)來漫遊用戶數據了。辦公開發也更加豐富了,包括對Office 2007 Ri on的集成支持。WCF和Workflow項目和設計器也包括在VS 2008中了。單元測試的速度大為提高,而且單元測試的支持包括在VS Profe ional版本(而不僅僅是VSTS版了)中了。連續集成支持也內置於TFS中了。AJAX web測試(單元和壓力)也由VS Test產品支持了。還有許許多多多的改進,這裡無法一一提及了。
注意事項
在安裝VS 2008 和.NET 3.5 Beta2之後,還有2件重要的事情你應該馬上做:
1) 你應該下載和運行這個批文件。這隻要幾秒鐘就可以運行完,它修補了這個星期早些時候我們發現的System.Web.Exte io .dll版本政策的問題,該程序集包含了 A .NET AJAX。如果你不運行這個批文件,那麼用A .NET AJAX 1.0 和 VS 2005構建的現有的A .NET 2.0項目就會自動地運載隨 .NET 3.5 Beta2發布的新A .NET AJAX 版本。這會工作而且運行良好,但會不小心導致你的VS2005應用依賴於.NET 3.5。運行這個批文件會改變新的System.Web.Exte io .dll程序集的版本綁定政策,確保你只在你明確構建.NET 3.5項目時才使用新的.NET 3.5 A .NET AJAX版本。
2) 假如你曾經在你的機器上安裝過Orcas或VS 2008的早期版本(Beta1 或某個CTP 版本)的話,你需要在安裝Beta2后重新設定你的VS 2008設置。如果你不這麼做的話,有些設置會非常奇怪(一些窗口在出現在奇怪的地方),你也有可能看到一些IDE性能問題。你可以在命令行上對VS 2008的IDE版本鍵入“DevEnv /resetsettings”來重新設定你的配置。

控制項


.NET標準控制項根據其應用環境分為兩類:
Windows Form控制項:主要用於Windows應用程序的開發。所有的Windows控制項都是從Control類中派生來的,該類包含了所有用戶界面的Windows Form組件,其中也包括Form類。Control類中包括了很多位所有控制項所共享的屬性、時間和方法。它包含複選框、文本框、按鈕、標籤、圖像列表等。
Web窗體控制項:主要用於Web應用程序的開發。它是專門針對Asp.NETWeb窗體設計的伺服器控制項。Web窗體控制項包含在命名空間System.Web.UI.WebControls中,當用戶使用Visual Studio創建Web窗體頁面時,會自動在後台代碼文件中添加引用該命名空間的Using語句。
.NET Compact Framework 提供了可以滿足大多數設備項目需要的Windows Form控制項。若要使用這些控制項沒有的功能,可以從公共控制項派生您自己的自定義控制項。可以通過定義從 Control 類或從程序集中的現有 UserControl 繼承的公共類型創建自定義控制項。
最簡單的控制項自定義是重寫公共控制項的方法。例如,可以重寫 TextBox 控制項的 OnKeyPress 繼承方法,提供將輸入限制為數字字元的代碼。
如若覺得自定義控制項過於浪費時間和複雜,也可以從受信任的來源下載控制項,並通過添加引用來導入自定義控制項。支持這些自定義的.NET的控制項有:ComponentOne Studio,Spread,ActiveReports、MultiRow等。

加密處理


信息安全是計算機應用的首要問題之一,但關於.NET加密功能的範例卻少之又少。有鑒於此,本文探討了在.NET平台下加密/解密文件的一般過程,並提供了一個加密/解密文件的工具。
Web服務以不容置疑的態勢迅速發展,促使許多單位開始考慮.NET之類的開發平台。但是,出於對安全問題的擔心,一些單位總是對採用新技術心存顧慮。好在有許多成熟的安全和網路技術,例如虛擬私有網路(VPN)和防火牆等,能夠極大地提高Web服務應用的安全和性能,讓開發者擁有選擇安全技術的自由,而不是非得使用尚在發展之中的XML安全技術不可。
雖然安全是信息系統的首要問題,但有關.NET安全和加密工具的範例卻少之又少。看看大多數.NET書籍的目錄,找不到任何有關安全的題目,更不用說關於密碼系統的探討了。
有鑒於此,本文將介紹如何在VB開發中運用.NET的加密和密鑰生成類,提供一個可用來加密和解密文件的工具Cryption。有了這個工具,你就可以在硬碟上保存各種機密文件,例如所有的密碼/用戶名字信息、收支文件、以及其他想要保密的信息,還可以加密那些通過Internet發送的文件。加密技術的用途非常廣泛,你可以進一步定製本文提供的工具滿足某些特殊需要,例如增加批處理能力等。

安全威脅

攻擊和泄密是計算機面臨的兩大安全威脅。攻擊可能來自病毒,例如它會刪除文件、降低機器運行速度或引發其它安全問題。相比之下,泄密往往要隱蔽得多,它侵害的是你的隱私:未經授權訪問硬碟文件,截取通過Internet發送的郵件,等等。泄密還可能伴隨著攻擊,例如修改機密文件等。
針對泄密的最佳防範措施就是加密。有效的加密不僅杜絕了泄密,而且還防範了由泄密引發的攻擊。加密技術有時還用於通信過程中的身份驗證——如果某個用戶知道密碼,那麼他應該就是那個擁有這一身份的人。
然而必須說明的是,沒有一種防範泄密的安全技術是絕對堅固的,因為密碼有可能被未經授權的人獲得。

加密前提

首先,要想使用.NET的安全功能,就必須用Imports語句引入加密用的包。試驗本文涉及的任何代碼之前,請在VB代碼窗口的頂部加入下列Imports語句:
Imports System
Imports System.Text
Imports System.Security.Cryptography
第二,美國政府過去限制某些加密技術出口。雖然這些限制不再有效,.NET框架在Windows的出口版本中禁用了“高級”加密技術。如果你的 Windows不帶高級加密能力,可以從微軟網站下載更新包:對於Windows 2000,安裝Service Pack 2包含的High Encryption Pack;對於NT,安裝Service Pack 6a。對於Windows ME、95、98的用戶,IE 5.5也包含了High Encryption Pack。

工具概況

本文提供的工具可用來加密和解密文件,如果你急著給一些文件加密,只需直接啟動本文後面提供的工具即可。
這個工具提供了一個用來輸入文件名字的文本框和一個輸入密鑰的文本框,通過便捷的用戶界面提供加密、解密和密鑰生成功能。在圖一中,上方的文本框用來輸入待加密/解密文件的名字;下面的文本框用來輸入8個字元的密碼。執行加密操作之後將生成一個新的文件,這個經過加密的文件和原始文件在同一目錄下,文件名字也和原始文件的一樣,但加上了“xx”後綴,例如,假設原始文件是MyFile.txt,則加密得到的文件是MyFilexx.txt。
加密好之後,原始文件不一定非刪除不可,但一般來說最好刪除,因為加密的根本目的就是為了隱藏原始文件的數據。如果要從加密后的文件恢復出原始文件,在上面的文本框中輸入MyFilexx.txt,然後提供密碼,Cryption工具將創建一個與原始文件一樣的MyFile.txt文件。也就是說, Cryption把文件名字後面的“xx”看作是要求解密密文的標誌。
注意:加密文件之後如果忘記了用來加密該文件的密碼,再想恢復出原始文件就不可能了。當然,這與密碼本身的複雜程度有關,要想保證文件的安全,最好採用較複雜的密碼,例如混合運用字母、數字和特殊字元(如“$”符號等)。
.NET提供的加密技術不止一種,不過本文討論的主要是對稱加密。對稱加密也稱為私有密鑰加密,它的特點是加密和解密用的是同一個密鑰(實際上是同一種演演算法),解密方和加密方都有責任保障密碼的安全(對於公用密鑰、不對稱加密,密鑰一共有兩個,其中一個密鑰是公開的,這是當前公認最有效的加密技術,但就速度而言要比對稱加密演演算法慢不少)。
在正式利用.NET加密類加密文件之前,首先必須從用戶提供的密碼生成一個密鑰。密鑰可以利用Hash函數生成,Hash函數把用戶的密碼字元串轉換成一組類似隨機數序列的、無意義的數據,這組數據可作為密鑰使用,在加密過程中對原始數據進行唯一性變形處理。
例如,用密鑰加密數據的一種辦法是把原始數據的ASCII碼加上密鑰的ASCII碼:
密鑰:ab = ASCII: 97,98
數據:merry = ASCII: 109,101,114,114,121
把這組數據的ASCII碼加上密鑰的ASCII碼(必要時重複使用密鑰),得到的加密結果是:
97 98 97 98 97
+109 +101 +114 +114 +121
206 199 211 212218
對於同樣的數據,Hash演演算法總是生成同樣的結果(這就是說,對於同一個密碼,同一Hash演演算法總是生成相同的bit序列)。實際上,在本文提供的代碼中,利用.NET的SHA1CryptoServiceProvider類的ComputeHash方法可以驗證這一點,例如,對於同一個輸入參數 morph,任何時候該方法總是返回下面的結果:124,230,93,253,197,206,136,72。因此,如果有人知道密碼以及生成密鑰的演演算法,他也可以輕鬆地推算出密鑰。

加密/解密

.NET加密技術要求密鑰有確定的長度,例如,DES(Data Encryption Standard)函數要求密鑰的長度是64位,Rijndael則要求128、192或256位長度的密鑰。密鑰越長,加密強度越高。對於DES之外的加密演演算法,查詢LegalKeySizes屬性即可得到它允許的密鑰長度,包括MinSize(支持的最小密鑰長度)、MaxSize(最大密鑰長度)、 SkipSize(增量)。SkipSize表示密鑰最大長度和最小長度之間可用長度的間隔,例如,Rijndael演演算法的SkipSize值是64位。
利用下面的代碼可以得到密鑰的長度信息:
' 創建DES加密對象
Dim des As New DESCryptoServiceProvider()
Dim fd() As KeySizes
fd = des.LegalKeySizes() 'tells us the size(s),in bits
MsgBox("加密類型=" & des.ToString() & Chr(13) & "minsize = " & fd(0).MinSize & Chr(13) & _
"maxsize = " & fd(0).MaxSize & Chr(13) & "skipsize = " & fd(0).SkipSize)
運行上面的代碼,得到的結果是64、64、0。如果把加密對象的聲明改成TripleDESCryptoServiceProvider(),得到的結果是128、192、64。
說明:DES演演算法要求輸入一個8位元組的密碼,但實際使用的密鑰只有56位(7個位元組),每一個位元組的最後一位不用(它作為校驗位使用,但不用於實際的加密過程)。
下面的代碼開始生成本文示常式序的密鑰:
Public Class Form1
Inherits System.Windows.Forms.Form
' 保存密鑰的8位元組的數組
Private TheKey(7) As Byte
' 在向量中放入一些隨機數據
Private Vector() As Byte = {&H12,&H44,&H16,&HEE,&H88,&H15,&HDD,&H41}
首先,代碼定義了保存密鑰和初始向量(請參見稍後的詳細說明)的兩個變數。向量的初值這裡用隨機數據填充,當然,通過密碼和Hash演演算法也可以獲得向量的初值。下面的過程從用戶輸入的密碼創建出密鑰:
Sub CreateKey(ByVal strKey As String)
' 保存密鑰的位元組數組
Dim arrByte(7) As Byte
Dim AscEncod As New ASCIIEncoding()
Dim i As Integer = 0
AscEncod.GetBytes(strKey,i,strKey.Length,arrByte,i)
' 獲得密碼的Hash值
Dim hashSha As New SHA1CryptoServiceProvider()
Dim arrHash() As Byte = hashSha.ComputeHash(arrByte)
' 將Hash值保存到密鑰
For i = 0 To 7
TheKey(i) = arrHash(i)
Next i
End Sub
用戶的密碼(strKey)傳入到CreateKey過程,分解成一組ASCII值保存到一個位元組數組。把這個位元組數組傳遞給 SHA1CryptoServiceProvider類的ComputeHash方法,返回一個Hash值。把這個Hash值保存到TheKey數組,供以後的加密/解密過程使用(注意SHA1CryptoServiceProvider實際能夠支持160位,但本文示常式序只用到64位)。
那麼,初始向量究竟起什麼作用呢?這個位元組數組有8個元素,就象密鑰一樣,但向量和密鑰的作用是不同的,向量用來避免DES之類的演演算法一個特有的問題。在DES之類的演演算法中,原始數據被分成8位元組一塊然後分別處理。DES在加密一塊數據時,要用到前一塊數據的模式,也就是說,如果改動了原始數據中第一塊的某個字元,所有後繼的塊的內容都將隨之改變,從而避免了一系列相連接的塊中出現重複塊的問題。
例如,假設你一時高興,發了一個郵件,內容只有幾個重複的單詞“Melanie! Melanie! Melanie! Melanie!”,在密鑰和塊序列中前一塊的共同作用下,加密之後的密文不會出現重複現象。然而,進一步考慮這個加密過程可以發現,如果用同一個密鑰加密多個郵件,且郵件開頭的問候語都相同,則郵件開頭的一部分很容易受到攻擊。由於這個原因,我們用初始向量來模擬前一個塊。
本文加密/解密工具中的下面這段代碼示範了如何加密文件:
Sub Encrypt(ByVal inName As String,ByVal outName As String )
Try
' 創建緩衝區
Dim storage(4096) As Byte
' 已經寫入的位元組數量
Dim totalBytesWritten As Long = 8
' 每次寫入的位元組數量
Dim packageSize As Integer
' 聲明文件流
Dim fin As New FileStream(inName,FileMode.Open,FileAccess.Read)
Dim fout As New FileStream(outName,FileMode.OpenOrCreate,FileAccess.Write)
fout.SetLength(0)
'源文件的大小
Dim totalFileLength As Long = fin.Length
' 創建加密對象
Dim des As New DESCryptoServiceProvider()
Dim crStream As New CryptoStream(fout,_
des.CreateEncryptor(TheKey,Vector),_
CryptoStreamMode.Write)
' 輸出加密后的文件
While totalBytesWritten < totalFileLength
packageSize = fin.Read(storage,0,4096)
crStream.Write(storage,0,packageSize)
totalBytesWritten = Convert.ToInt32(totalBytesWritten + _
packageSize / des.BlockSize * des.BlockSize)
End While
crStream.Close()
Catch e As Exception
MsgBox(e.Message)
End Try
End Sub
注意這段代碼創建了三個文件流:fin,表示明文形式的原始文件;fout,加密結果文件;crStream,加密流,用來把DES加密的結果轉入輸出文件fout。增加一個crStream流的好處是不必把結果保存到臨時文件或緩衝區。
加密過程與解密過程的唯一重要區別是,執行解密時,我們將使用DESCryptoServiceProvider對象的另一個方法CreateDecryptor,除此之外,兩者其餘的處理步驟(包括參數,文件流,等等)基本相同。

防止破解

黑客和密碼專家破解加密文件的辦法主要有兩個,第一是搜索密文是否有重複現象,第二是用暴力破解法獲得密鑰。首先我們考慮一下初始向量如何防止重複現象,然後再探討一下防止暴力破解的關鍵問題。
破解密文的第一種方式是搜索樣本——特別是重複的樣本。人們在寫信的時候總是喜歡用同樣的文字開頭,例如“親愛的XXX”、“Dear Sir”等,如果多個郵件的開頭文字相同且通過同一密鑰加密,則每個密文信件的開頭也相同。假設Antonio寫給Melanie的所有加密信件都有相同的問候語“@4^F (2$@Fx”,解密者就會首先檢查開頭的幾個單詞是不是“Dear Melanie”。解密機密文件的一個重要步驟就是猜測文件中應當會出現的幾個單詞,所以我們不應該給解密者提供這種方便。在本文的示例中,初始向量的內容被附加到文件的開頭,從而防止了出現重複現象。只有信件的開頭才容易受到此類攻擊。
計算機的運算速度和精度要遠遠超過人,特別擅長處理一些重複的任務,例如嘗試每一種可能的密鑰組合最終破解密鑰。DES加密演演算法本身是不安全的,這種加密演演算法早在70年代就已經公之於眾。而且,破解者如果想要讓搜索密鑰的過程自動化,同樣可以方便地運用.NET的DESCryptoServiceProvider類。
對於一個128位、結合運用密鑰/初始向量的加密方案,計算機嘗試每一種可能的密鑰組合要花多少時間?專家們的看法並不一致,有人認為需要數月,也有人認為裝有專用硬體的價值6位數的計算機每秒能夠驗證數十億個密鑰,破解DES密文只需數小時。如果你的機密值得花數月時間去破解,那麼最好改用 TripleDES或其他加密演演算法。從TripleDES的名字也可以猜出,這種加密方式採用三重數據加密標準演演算法,所以密鑰的長度是192位,而不是 64位的DES密鑰。記住,在其他條件相同的情況下,密鑰越長,安全程度越高。
結束語:現在你已經了解了. NET DES加密演演算法的使用過程,接下去可以研究.NET的其他安全功能,包括極具吸引力的公用密鑰加密方案。雖然公用密鑰加密方案執行起來速度慢一些,但加密效果一般要比TripleDES好。

未來發展


預測未來,在技術世界是常有的事兒。從高級語言的發展歷史來看,編程世界從來就沒有停止過腳步,變革時時發生、創新處處存在。以技術人員的角度來觀摩未來,帶著C# 4.0的腳步來看展望,除了在函數式編程、并行計算和動態特性上大展拳腳,Meta Programming的概念已然浮出水面,將編譯器變成一個Service,你可以自由控制在編譯器和運行期的邏輯,那是多麼美好而嚮往的未來呀,所以,我們堅信 4.0之後還有廣闊的天地隨著語言的變遷變得更加開闊。
概括Anders大師在C#設計過程中的思想,C#是語言美學的集大成者。例如,當使用foreach進行循環遍歷之後,當應用using語句代替try/finally實現強制資源管理,當應該attribute進行運行時反射,當以LINQ進行語言級別的信息查詢,這些語言級別的支持為C#實現面向對象編程帶來強大的功能動力和美學感受。

書籍


C#程序設計
C# Primer中文版
.NET框架程序設計(修訂版)
c#Windows程序設計
.NET程序設計技術內幕
.NET本質論--第1卷:公共語言運行庫(中文版)

註冊規則


1、只提供英文字母(a-z,不區分大小寫)、數字(0-9)、以及"-"(英文中的連詞號,即中橫線),不能使用空格及特殊字元(如!、$、&、? 等)。
2、"-"不能用作開頭和結尾。
3、長度不能超過63個字元。
4、簡單、易記,邏輯性強(與企業商標、產品名稱吻合;根據網站的性質、用途選擇)。
5、為同一個域名註冊多個不同後綴。
6、域名購買年限選擇2年以上。

注意問題


1、域名安全與產權方面來說:一定要正確填寫域名的所有人(這項非常重要,是關係到域名的產權問題及以後的域名過戶、轉移註冊商等問題)、註冊聯繫人及身份證、管理聯繫郵箱(郵箱必須是經常使用的,以便續費的時收到提醒通知); 如果註冊信息發生變化,應當及時更新。
2、域名註冊時候最好選擇好用、易記的域名,以便於宣傳和推廣。
3、注意全方位保護自己的域名品牌,現在網際網路上域名已經成為寶貴的域名資源,如果你註冊了一個域名之後,最好將相關的域名也註冊下來,以避免被別人搶注。例如 註冊了.com域名,可以同時將.net、.cn、.com.cn、.net、.cn、.info 等這些域名同時保護起來。適當的時候要考慮將一些類似的域名也註冊掉。
4、除了傳統的.cn、.com、.net等純英文域名後綴之外,還有以“.中國”結尾的純中文域名,並且註冊“中文.CN”將自動獲得對應的“中文。中國”域名,獲贈繁體中文,無需另行申請註冊。
對於企業用戶,最好還要註冊自己的中文域名,做到面面俱全,以鎖定自己在網際網路上絕對安全和品牌壟斷權。
5、為避免域名過期導致要高價贖回,或是被搶注而要付出高成本代價,或是解析暫停影響網站訪問的情況,按時續費也是非常重要的。所有域名過期后30天內可正常續費。