兩個問題是:
◆寫程式時少了智能感知;
◆運行程式時速度變慢(反射)。
今天看完New features in CSharp
4.docx才恍然明白,趁著沒事,把東西整理一下,希望能對暫時還不明白dynamic有什麼用的朋友提供一些參考。當然,由於本人才疏學淺,不保證所有的觀點都是正確的,希望大家用辯證的眼光來看這篇文章,如有錯誤之處,請大夥批評指正。
言歸正傳,dynamic關鍵字用於聲明一個動態對象,然後通過該動態對象去調用方法或讀寫屬性。
在使用C#
2.0或3.0的時候,如果一個對象需要在運行時才能確定,並且沒有介面和基類方面的資訊,那我們一般使用反射技術來調用這個未知對像的方法或屬性,而C#
4.0提供的dynamic可以幫我們簡化這些工作。假設我們的程式會在運行時取得一個不確定類型的對象,但這個對象一定會有個Print()方法,我們需要調用這個方法列印出一些資訊,那麼在C#
4.0下面,我們可以用下面的兩句代碼來實現這個需求。
這種解決方式比起用反射調用Print方法,應該簡潔很多吧?程式員要做的就是別把方法名Print()打錯,VS2010是不會為dynamic對象提供智能提示的,因為VS不知道運行時這個unknowObj會是什麼東東……
到這裡,應該有不少的朋友可以從這個例子上看出,當程式編譯到unknowObj.Print()的時候,VS會幫我們產生反射的代碼,用反射的方式去調用Print這個方法,實質上就是幫我們自動反射了。
如果能理解這一點,那也就不難理解C#為啥要搞dynamic這個既沒智能感知,運行又慢的怪物出來了。
按New features in CSharp 4的說法,dymanic主要應用於下面的情境:
1、自動反射
2、COM組件互操作
3、混合編程,例如IronRuby和IronPython
4、處理Html DOM對象
如果有處理過上面這些工作的朋友們,應該不難理解了吧。
具體的內容,還請大夥自己看看New features in CSharp 4,裡面說得比較詳細。以上介紹C# 4.0的dynamic。
C#4.0的dynamic用法(一)——巧用反射
本文來自-拍搜學院:http://www.pasou.cn/edu/html/List18250.html
在平時做架構架構設計的時候,頭疼之一的是處處得採用反射,但有了C#4.0,發現dynamic完全可以取代反射,這個功能讓我有些激動,立馬在VS2010將日誌跟蹤器架構裡的第一個反射的代碼升級到C#4.0,結果一點都不令人失望,代碼簡化了很多。
先看看用dynamic替換反射後的代碼吧:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Reflection;
6 using System.IO;
7 /********************************
8 * Updated by Lihua at 03/13/2009
9 *
10 * 更新功能:
11 * 1. 升級到C#4.0,加入dynamic代替反射
12 * 2. 如果Zivsoft.Log.dll不存在,日誌不輸出
13 * 3. 項目編譯不依賴於Zivsoft.Log.dll
14 ****************************************/
15 namespace Zivsoft.Data
16 {
17 /// <summary>
18 /// 只提供持久資料層架構裡的類使用
19 /// </summary>
20 internal class Logger
21 {
22 private static Assembly _assemblyFile;
23 private static dynamic _logger;
24 static Logger()
25 {
26 var strDllFile = AppDomain.CurrentDomain.BaseDirectory + "Zivsoft.Log.dll";
27 if (File.Exists(strDllFile))
28 {
29 _assemblyFile = Assembly.LoadFile(strDllFile);
30 try
31 {
32 _logger = _assemblyFile.CreateInstance("Zivsoft.Log.Logger", false, BindingFlags.CreateInstance, null, null, null, null);
33 }
34 catch {
35 _logger = null;
36 }
37 }
38 }
39
40 public static void LogInfo(string message, params object[] args)
41 {
42 if (null != _logger)
43 {
44 _logger.LogInfo(message, args);
45 }
46 }
47
48 public static void LogWarning(string message, params object[] args)
49 {
50 if (null != _logger)
51 {
52 _logger.LogWarning(message, args);
53 }
54 }
55
56 public static void LogError(string message, params object[] args)
57 {
58 if (null != _logger)
59 {
60 _logger.LogError(message, args);
61 }
62 }
63
64 public static void LogDebug(string message, params object[] args)
65 {
66 if (null != _logger)
67 {
68 _logger.LogDebug(message, args);
69 }
70 }
71
72 public static void LogError(Exception e)
73 {
74 LogError("{0}", e);
75 }
76 }
77 }
78
以上是持久資料層調用日誌跟蹤器的入口代碼,以前採用反射,剛被我用dynamic改了過來,經調試一點問題都沒有,所以這讓我欣喜,因為接下來的我的很多架構採用反射的機制將都可能被dynamic替換,比如《持久資料層架構》中的被反射的SQLServer, MySQL, Access等等資料庫。
不多寫了,大家仔細體會吧。
dynamic 應用之簡化COM互通性C# 4.0包含了多個特性,改進了與傳統COM API介面如Office自動化等的互通性。Dynamic類型、具名引數以及選擇性參數也屬於改進中的一部分。許多的COM方法允許其參數和傳回值類型為object,因此對於強型別語言如C#來說,就需要做大量的強制類型轉換。然而在C# 4.0中,如果在編譯時間加上/link選項,則dynamic類型就會起新的效果:它使得COM介面方法簽名中的object類型(參數類型或傳回型別)被視為dynamic,因而能夠避免大量的類型轉換工作。例如,下面的語句對此進行了對比。// 沒有用 dynamic.((Excel.Range)excel.Cells[1, 1]).Value2 = "Name";Excel.Range range = (Excel.Range)excel.Cells[1, 1];// 用了dynamic, excel.Cells[1, 1].Value = "Name";Excel.Range range = excel.Cells[1, 1];
dynamic應用之混合編程(下面是利用dynamic調用IronPython的例子)
using IronPython.Hosting;using Microsoft.Scripting.Hosting;Console.WriteLine("Loading random.py...");ScriptRuntime py = Python.CreateRuntime();dynamic random = py.UseFile("random.py");Console.WriteLine("random.py loaded!");var items = Enumerable.Range(1, 7).ToArray();for (int s = 0; s < 10000; s++) { random.shuffle(items); Console.Write("Sequence {0}: ", s); foreach (int i in items) { Console.Write("{0} ", i); } Console.WriteLine();}對於類型為dynamic的對象或者運算式,編譯器的角色就是將每個運算式預期執行的動作封裝起來,在運行時刻,對儲存的資訊進行檢查,任何無效語句均會觸發運行時異常。大多數dynamic操作的結果的類型也是dynamic的。例如,如果將滑鼠指標停留在下例的testSum上,智能提示會顯示 (local variable) dynamic testSum。dynamic d = 1;var testSum = d + 3;// 將滑鼠指標停留在下面的testSum上.System.Console.WriteLine(testSum);