2010年2月11日 星期四

C# 4.0 : dynamic language (1)

在 C# 4.0,增加了動態語言的特性。

簡單地說,使用 dynamic 宣告出來的變數,在編譯器編譯時期會被省略不編譯,直到執行期到動態地解譯所使用的 member field,  member function 或 function。

舉例來說,下面的程式會發生編譯錯誤。原因是 object 這種類別沒有 Name 的屬性。

例1
   1: class C1
   2: {
   3:   public string Name { get; set; }
   4: }
   5: class Program
   6: {
   7:   static void Main(string[] args)
   8:   {
   9:     C1 c1 = new C1() { Name = "a" };
  10:     WriteName(c1);
  11:   }
  12:   public static void WriteName(object o)
  13:   {
  14:     Console.WriteLine(o.Name);
  15:   }
  16: }

想要讓這個程式碼 compile 通過當然是很容易的事,只需要將 WriteName 的參數由 object 型別改成 C1 型別即可。

以下這一段程式,想要寫一個能印出物件的 Name 屬性的共用程式 WriteName。

例2
   1: class C1
   2:   {
   3:     public string Name { get; set; }
   4:   }
   5:   class C2
   6:   {
   7:     public string Name { get; set; }
   8:     public int Id { get; set; }
   9:   }
  10:   class Program
  11:   {
  12:     static void Main(string[] args)
  13:     {
  14:       C1 c1 = new C1() { Name = "a" };
  15:       C2 c2 = new C2() { Name = "b", Id = 1 };
  16:       WriteName(c1);
  17:       WriteName(c2);
  18:     }
  19:     public static void WriteName(C_What o)
  20:     {
  21:       Console.WriteLine(o.Name);
  22:     }
  23:   }

WriteName 的參數1,應該宣告 C1 還是 C2 呢?都不行,靜態語言是不會過的。精通物件導向的我們,當然知道此時最好使用 interface 來解決問題。如下。

例3
   1: interface IName
   2:   {
   3:     string Name { get; set; }
   4:   }
   5:   class C1 : IName
   6:   {
   7:     public string Name { get; set; }
   8:   }
   9:   class C2 : IName
  10:   {
  11:     public string Name { get; set; }
  12:     public int Id { get; set; }
  13:   }
  14:   class Program
  15:   {
  16:     static void Main(string[] args)
  17:     {
  18:       C1 c1 = new C1() { Name = "a" };
  19:       C2 c2 = new C2() { Name = "b", Id = 1 };
  20:       WriteName(c1);
  21:       WriteName(c2);
  22:     }
  23:     public static void WriteName(IName o)
  24:     {
  25:       Console.WriteLine(o.Name);
  26:     }
  27:   }

這樣一來,解決了 C1, C2 的問題。「只」需要實作 IName 的介面,就可以使用 WriteName 這個函數了。

問題就在 IName 是一個自訂的介面,不是通用的介面。別人寫好的類別,絕對不會知道及實作我們自訂的 IName 介面。如果我們的WriteName 想要通吃呢?下面的程式就是使用 Reflection 機制寫出來的 solution

例4
   1: class C1
   2:   {
   3:     public string Name { get; set; }
   4:   }
   5:   class C2
   6:   {
   7:     public string Name { get; set; }
   8:     public int Id { get; set; }
   9:   }
  10:   class Program
  11:   {
  12:     static void Main(string[] args)
  13:     {
  14:       C1 c1 = new C1() { Name = "a" };
  15:       C2 c2 = new C2() { Name = "b", Id = 1 };
  16:       WriteName(c1);
  17:       WriteName(c2);
  18:     }
  19:     public static void WriteName(object o)
  20:     {
  21:       Type type = o.GetType();
  22:       string str = (string)type.GetProperty("Name").GetValue(o, null);
  23:       Console.WriteLine(str);
  24:     }
  25:   }

這個方式,一律使用 object 來接參數,再使用 Reflection 的機制來動態的取得 Name 的 property,並當成字串輸出到 Console。棒吧!

可是,這段程式有點難寫耶!如果一次要取得三個property,並執行傳入參教的某個 function,就累翻了。

最後,則是使用 dynamic 的宣告,將例3的 C_What 改成 dynamic 即完成了

例5

   1: class C1
   2:   {
   3:     public string Name { get; set; }
   4:   }
   5:   class C2
   6:   {
   7:     public string Name { get; set; }
   8:     public int Id { get; set; }
   9:   }
  10:   class Program
  11:   {
  12:     static void Main(string[] args)
  13:     {
  14:       C1 c1 = new C1() { Name = "a" };
  15:       C2 c2 = new C2() { Name = "b", Id = 1 };
  16:       WriteName(c1);
  17:       WriteName(c2);
  18:     }
  19:     public static void WriteName(dynamic o)
  20:     {
  21:       Console.WriteLine(o.Name);
  22:     }
  23:   }

例5 的語法與例3幾乎完全一樣,但事實上走的是例4的執行時間Reflection 機制。大大地節省了程式碼的撰寫。

由執行時期才決定資訊的機制,就是動態語言的特性。

2010年2月9日 星期二

VS2010 RC 今天出來了

今天 (2010/02/09)出來的,只能從英文版的 msdn subscriptions。繁體中文件介面還看不到。

正式版預計 4/12 出來。

後記:(2010/02/12)
公開下載的位置,資訊更完整,連同 Visual Studio 2010 SDK 等也一起出來公開下載了。

2010年2月6日 星期六

MVC 2.0 RC2 又出來了

沒多久前,才出了 RC 版,現在又出了 RC2 了。

版本說明請見 haacked 的 blog

2010年2月3日 星期三

要開發 VS2010,最好記憶體多多

Visual Studio 2010 預計在 2010/04/12 發佈正式版。
其中最引我注意的,是開發機器硬體等級需求大幅提高。
據可靠消息,最好有 3GB 的記憶體,跑起來才會順。

2010年1月27日 星期三

自動翻譯的笑話

今天碰到的。

http://support.microsoft.com/kb/943847/zh-tw 是中文版,內容說該檔案有毒。救命啊!微軟的網頁說自己的檔案有毒?

image

http://support.microsoft.com/kb/943847/en-us 是英文版,看一下原來的字句。
image

原來是微軟的自動翻譯錯了。竟然翻譯完全相反了。

Google 的翻譯可正確多了。

image

還是看原文的比較快。

使用 VSS (Volumn Shadow Copy Service) 備份 VM

在使用 Hyper-V 之前,最好先知道 VM 如何進行備份。如果沒有擬好策略,將來VM 要災難復原時,就求助無門了。

備份的方法分成四種,其中一個方法是使用 VSS (Volumn Shadow Copy Service) 備份 VM。也就是今天要介紹給大家的。

安裝 Windows Backup Features

目的,是在 Windows Backup 時,也能備份 VM。但,VM 在執行中時,VM 的檔案,如 *.vhd 是被 locked 住的,因此 windows 要如何進行備份呢?

首先,在 Hyper-V Host 上以 admin 權限執行 cmd,輸入

vssadmin list writers

結果會列出在該台機器上支援的 writer,也就是使用 vss 備份時可以不受限於lock 的方法。找到 Microsoft Hyper-V VSS Writer 的 Writer Id。如下資訊。
Writer name: 'Microsoft Hyper-V VSS Writer'
Writer Id: {66841cd4-6ded-4f4b-8f17-fd23f8ddc3de}
Writer Instance Id: {84261b8d-c19b-42f7-8463-c540d606495b}
State: [1] Stable
Last error: No error

寫機碼

沒錯,要自訂機碼。原來 Hyper-V VSS Writer 並不是預設啟用的。使用 regedit,在 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion 下新增一個名為 WindowsServerBackup 的 key。於 WindowsServerBackup 下再新增一個名為 Application Support 的 key。再於其下新增一個上個步驟的 Writer Id 的key,也就是 66841cd4-6ded-4f4b-8f17-fd23f8ddc3de。最後,再於其下新增一個 string value,名為 Application Identifier,值為 Hyper-V VSS Writer。

寫起來很複雜,其實就如下圖所示。

image

進行 Windows Server Backup

在 Administrative tools 下可找到 Windows Server Backup。這就是一般進行備份的工具。在此不多做介紹,坊間的書都有介紹。

附註說明的是,使用 Windows Server 2008 執行 Windows Server Backup,只能進行邏輯磁碟的備份,如 c, d, e 磁碟,並沒有辦法進行單一檔案的備份。因此,需要使用第三方軟體(也就是另外花$$買)。在 Windows Server 2008 R2,也增強了這方面的功能。

2010年1月22日 星期五

Cannot convert lambda expression to type 'string' because it is not a delegate type

開發程式程,當然預設使用 Linq 的語法。發現了一個錯誤,訊息如下
Error 234 Cannot convert lambda expression to type 'string' because it is not a delegate type
錯誤出現在下方的 linq 語法上

 

var ctx = new ProjectServerEntities();
string email = (from i in ctx.Resources
       where i.NAME == displayName
       select i.Email).SingleOrDefault();

怎麼看都沒問題啊!

原來是少了 using System.Linq;

天啊!誰看的懂哪。

Share with Facebook