SQL Server - 2008 R2 SP1 更新

升級至 SQL Server 2008 R2 SP1 ,下載 SQL Server 2008 R2 SP1:
2011/7/12 已經正式發行,或許你已經有透過 Windows Update 更新,先確認一下你的版本號「10.50.2500.0」即為 SQL Server 2008 R2 SP1。

或是在 master 資料庫執行以下 T-SQL 查詢:

SELECT SERVERPROPERTY('productversion'),SERVERPROPERTY('productlevel'),SERVERPROPERTY('edition')

就可以得到如: 「10.50.2500.0 SP1 Express Edition (64-bit)」這樣的結果,即能確定是否為最新SP1。

如果想知道更清楚的資料庫版本號對應,可以查詢這一篇「如何識別 SQL Server 的版本」文章,目前只更新至 SQL Server 2008版本號,SQL Server 2008 R2版本號還未更新上去。

補充:前面是 10.0.x 表代你是 SQL Server 2008, 10.50.x 表代你是 SQL Server 2008 R2。

參考資料:

Visual Basic - Login/登入/登錄之物件導向實作

Login VB-OOP 實作前言

Login (登入/登錄) 動作,不管在任何應用系統 (AP, Application System)都能看到它的影子。像我的手機,一開機先問個 PIN 密碼...光一個手機,就能有好多密碼。
  1. 進公司刷卡(Card);
  2. 提錢(Card);
  3. 上網(Accout/Password);
  4. 回家開門(Key);
  5. 開車(Key);
  6. 指紋(生物辨識);

你能發現每天從早到晚,其實都在不斷的 Login / Logout,出門上班,對「家」而言,你是 Logout,開車上班,對「車」而言,你是 Login,到達公司,對「車」而言,你是 Logout,進公司,必須刷卡才能進入,那是 Login,下班刷卡離開公司,那是 Logout。

指紋辨識,這幾年拜 NB 幫的忙,很多 NB 都把指紋辨識當成基本配備,省下了打 Keyboard 的時間,刷一下手指,超方便的。還記得,大學時在「國家太空中心」打工,國家太空中心可以使用「掌紋辨識」,在當時可以說是很先進方便,辨識率也不錯,就我在那裡打工時間裡,最少沒有出錯過。

以下是以程杰(大話設計模式作者) Blog 裡兩篇文章為基礎,以這兩篇文章實作出 Visual Basic 可執行版本。

  1. 凭什么要用面向对象编程——面向对象重要设计原则概述
  2. 凭什么要用面向对象编程(补充)
非常推薦給學習過物件導向的人來看,Login 範例非常實用,只要是「AP」你一定會碰到 Login 問題,學習如何透過物件導向來處理此一問題。

我覺得另一重點是「思緒」,想想,如果是你,你會怎麼處理?是否會有一樣的思緒?而且我認為文章中提出的問題,都還算常見,不算是那種為了寫書或寫文章而特別設計的例子。

範例一:網頁登入 (CodeBehind) (對應文章 2007-7-1  對話)



WebForm_1 專案 - Login.aspx

Login.aspx 介面 HTML。

<h2>網頁登錄 ( CodeBehind )</h2>
<form id="form1" runat="server">
<div>
    <asp:Label ID="lbName" runat="server" Text="帳號:"></asp:Label>
    <asp:TextBox ID="tbName" runat="server"></asp:TextBox>
    <br />
    <asp:Label ID="lbPassword" runat="server" Text="密碼:"></asp:Label>
    <asp:TextBox ID="tbPassword" runat="server" TextMode="Password"></asp:TextBox>
    <br />
    <br />
    <asp:Button ID="btnLogin" runat="server" Text="登錄" />
</div>
</form>

Login.aspx.vb CodeBehind 程式碼。

Public Class Login
    Inherits System.Web.UI.Page

    Protected Sub tbLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
        Dim userName As String = tbName.Text
        Dim passWord As String = tbPassword.Text

        If (login(userName, passWord)) Then
            Response.Redirect("LoginOK.aspx")
        Else
            Response.Redirect("LoginFail.aspx")
        End If
    End Sub

    Private Function login(userName As String, password As String) As Boolean
        ' 訪問資料庫,進行帳號及密碼比對
        ' --- 此處只是為了 Demo 方便,所以寫死 ---
        If userName = "kkbruce" And password = "12345" Then
            Return True
        Else
            Return False
        End If
    End Function

End Class

此範例為最最最基礎的 Login 程式碼,也是最最最一般的 Login 程式碼。注意,為了 Focus 在「Login」這件事情上面,我們的範例不會出現任何資料庫相關程式碼,要注意的地方,我都有打上註解。

另外準備兩個網頁, LoginOK.aspx及LoginFail.aspx,內容很簡易,一個打上「網頁登錄成功!」,一個打上「網頁登錄失敗!」,執行我們的第一個專案,這已經是一個能動的範例了。

範例二:手機登錄 ( Class UserAdmin ) (對應文章 2007-7-25 對話)


我個開一個新 WebForm 專案,假設它是手機登錄介面。

WebForm_2 專案 - Login.aspx


PhoneLogin.aspx 介面 HTML 同 WebForm_1 專案。

PhoneLogin.aspx.vb

Public Class Login
    Inherits System.Web.UI.Page

    Protected Sub tbLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
        Dim userName As String = tbName.Text
        Dim password As String = tbPassword.Text

        ' 使用 Class UserAdmin 提供的認證功能。
        Dim ua As New UserAdmin
        If (ua.Login(userName, password)) Then
            Response.Redirect("LoginOK.aspx")
        Else
            Response.Redirect("LoginFail.aspx")
        End If
    End Sub
End Class

''' <summary>
''' 用戶管理類別
''' </summary>
Public Class UserAdmin

    ''' <summary>
    ''' 登錄資料確認函式
    ''' </summary>
    ''' <param name="userName">帳號</param>
    ''' <param name="password">密碼</param>
    ''' <returns>Boolean</returns>
    Public Function Login(userName As String, password As String) As Boolean
        ' 訪問資料庫,進行帳號及密碼比對
        ' --- 此處只是為了 Demo 方便,所以寫死 ---
        If userName = "kkbruce" And password = "12345" Then
            Return True
        Else
            Return False
        End If
    End Function
End Class

我們把原本的 Login 函式提升至一個 UserAdmin 類別裡,這樣就可以給大家共用。


Tool - USB 傳輸速率測試理論值 (Experimental Theoretical Values)

我去買了一條 USB 3.0 A公對A母的傳輸線,包裝上有一 USB 傳輸速率比較表,我覺得不錯。

USB 傳輸速率測試理論值 (Experimental Theoretical Values)
Data TypeSong/Picture256 FlashUSB FlashSD-MovieHD-Movie
Size4 MB256 MB1 GB6 GB25 GB
USB 1.15.3 Sec5.7 min22 min2.2 hr9.3 hr
USB 2.00.1 Sec8.5 Sec33 Sec33 min13.9 min
USB 3.00.01 Sec0.8 Sec3.3 Sec20 Sec70 Sec

特別說明:此為理論值,但目前的設備 ( HDD ...)能達到 USB 3.0 全速,印象中好像沒有。不過 USB 3.0 的設備真的比 USB 2.0 快,可參考「Tools - USB 3.0 隨身碟 Speed 測試」。

Tools - USB 3.0 隨身碟 Speed 測試

最近買了幾樣新玩具,其中一項是隨身碟。因為家中新主機有支援 USB 3.0 介面,所有當然是找 USB 3.0 介面為主的隨身碟。不過,一般而言,USB 3.0 介面的硬體還是單價比較高。

不過也讓我找到一支便宜又支援 USB 3.0 的隨身碟,更重要的是「終身保固」。因為我的前一支隨身碟,到目前為止,前後換了二次 (第三支),也就是說,還好有「終身保固」,反正有問題就換新的一支給你。目前有很多是「保固五年」,那種我根本不考慮。

Silicon Power Blaze B10 USB3.0 8GB vs 8GB JetFlash V10隨身碟

以下為 Speed 測試,主要針對寫入來進行測試。

JF V10 vs Blaze B10 USB 2.0 port Write Speed


圖一:JF V10 USB 2.0 port write speed
圖二:Blaze B10 USB 2.0 port write speed


JF V10 vs Blaze B10 USB 3.0 port Write Speed


圖三:JF V10 USB 3.0 port write speed
圖四:Blaze B10 USB 3.0 port write speed


結論


圖四,讓我好失望,果然只是加大水管,出水量一樣。不過,單一檔案很大的話,速度的差異性還是有的。不要以為我的電腦沒有 USB 3.0 就傻傻的去買 USB 2.0 的硬體。如果價格你能接受,我會推薦以 USB 3.0 為主的硬體。以我使用 USB 2.0 / USB 3.0 外接硬碟的經驗,USB 3.0 外接硬碟複製數十 GB 的資料,差異時間與 USB 2.0 外接硬碟是以小時為單位。

看似差一點點,但當你把資料量放大,省下來時間可多了。以上,是我的無聊比較文!

中秋節快樂。

Visual Basic - Reflection, 反映教學筆記(10) Object-oriented 物件導向範例程式

Class 圖表

我們先看來整個 Class 圖表

圖一:Assembly Object-oriented Class (一) (點擊看大圖)
重點在 SampleFactory,SampleFactory是類別產生工廠。

圖二:Assembly 相關類別 (點擊看大圖)
我們透過一個抽象類別 SuperAssembly 來整理所有的初始化及屬性工作,直接繼承使用。

圖三:Attribute 相關類別(點擊看大圖)
同上,透過抽象類別 SuperAttribute 來整理所有初始化及屬性工作,直接繼承使用。

Visual Basic - Reflection, 反映教學筆記(9) 執行環境中產生程式碼

總和前面所有,在這一篇裡,我們將整合前面所有內容,從無到有完完全全自行建立自有組件、自有模組、自有型別、自有成員、自有方法、自有欄位、自有屬性,最後還能將動態建立的組件儲存成實體組件檔案 ( *.dll )。

一樣,應該要注意的內容,我都註解到程式碼中,與前一篇「Visual Basic - Reflection, 反映教學筆記(8) 執行動態程式碼」很像,就是 Step by Step 的建立出你的組件。重點在於我們是使用 System.Reflection.Emit 類別*Builder 結尾的類別,來動態建立出我們的組件。

*Builder 結尾的類別類似觀念,我們前面「」就已經談過,觀念一樣,我就不在重覆。你要建立什麼就是 ...Builder 類別。記的要先Imports System.Reflection.Emit。

RunTimeCreateAssembly 副程式

#Region "執行環境中產生程式碼"
    ''' <summary>
    ''' 建立動態組件
    ''' </summary>
    Private Sub RunTimeCreateAssembly()
        ' 1. 建立組件
        Console.WriteLine("定義組件")
        Dim tempName As New AssemblyName()
        tempName.Name = "KKBruceSampleAssembly"
        tempName.Version = New Version("1.0.0.0")

        ' 使用 DefineDynamicAssembly 動態產生組件
        Dim AssemBL As AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(tempName, AssemblyBuilderAccess.RunAndSave)

        ' 2. 建立模組
        Console.WriteLine("定義模組")
        ' DefineDynamicModule 動態產生模組
        ' 如果要建立一個單一檔案的組件,並將此組件序列化在磁碟之中,最後的Save名稱必須與以下DefineDynamicModule裡名稱相同。
        Dim ModuleBL As ModuleBuilder = AssemBL.DefineDynamicModule(tempName.Name, tempName.Name & ".dll")

        ' 3. 建立型別
        Console.WriteLine("定義型別")
        ' DefineType 動態產生型別
        Dim BruceType As TypeBuilder = ModuleBL.DefineType("KKBruceType", TypeAttributes.Class Or TypeAttributes.Public)
        ' 指定父類別及介面給DefineType
        'Dim tb As TypeBuilder = mb.DefineType("KKBruceMyNewType", TypeAttributes.Class Or TypeAttributes.Public,
        '                                      GetType(Hashtable),
        '                                      New Type() {GetType(IDisposable)})


        ' 4. 建立成員
        Console.WriteLine("定義相關成員")
        ' 4.1 建立建構子
        Console.WriteLine("     定義建構子")
        ' MethodAttributes代表建構子的類型
        'Dim ConstructorBL As ConstructorBuilder = BruceType.DefineDefaultConstructor(MethodAttributes.Public)

        ' 4.2 利用ConstructorBuilder建立ILGenerator物件

        ' --- 註:執行會產生錯誤 ---
        ' --- 註:依MSDN查詢:Runtime 會為預設建構函式產生程式碼。因此,如果嘗試取得 ILGenerator,則會擲回例外狀況。 ---

        'Console.WriteLine("     建立ILGenerator物件")

        ' ILGenerator 可產生 Microsoft Intermediate Language (MSIL) 指令。
        'Dim codeGen As ILGenerator = ConstructorBL.GetILGenerator()

        ' Emit:多載。放置指令到 Just-In-Time (JIT) 編譯器的 Microsoft Intermediate Language (MSIL) 資料流中。
        ' OpCodes 類別:提供 Microsoft Intermediate Language (MSIL) 指令的欄位表示,以用於 ILGenerator 類別成員 (例如 Emit) 的發出。
        ' Ret欄位:從目前方法傳回,將被呼叫端評估堆疊的傳回值 (如果有的話) 推入至呼叫端的評估堆疊。 
        'codeGen.Emit(OpCodes.Ret)

        ' 4.3 建立方法
        Console.WriteLine("     定義方法")
        Dim MethodBLOne As MethodBuilder = BruceType.DefineMethod("AddStringOne", MethodAttributes.Public, Nothing, New Type() {GetType(String)})
        ' 第三個參數:建新新方法的回傳型別
        ' 第四個參數:參數型別
        Dim MethodBLTwo As MethodBuilder = BruceType.DefineMethod("AddStringTwo", MethodAttributes.Public Or MethodAttributes.Static,
                                                     Nothing,
                                                     New Type() {GetType(String)})

        ' 4.4 建立私有欄位
        Console.WriteLine("     定義私有欄位")
        Dim FieldBL As FieldBuilder = BruceType.DefineField("_count", GetType(Int32), FieldAttributes.Private)

        ' 4.5 建立屬性
        Console.WriteLine("     定義屬性")
        ' PropertyAttributes.None 列舉常數不能定義所有的屬性
        Dim PropertyBL As PropertyBuilder = BruceType.DefineProperty("Count", PropertyAttributes.None, GetType(Int32), Type.EmptyTypes)

        ' 4.6 在方法中定義設得或設定屬性值
        Console.WriteLine("     定義方法中設得或設定屬性值")
        ' 注意,使用MethodAttributes
        Dim getMethodAttributes As MethodAttributes = MethodAttributes.Public Or
                                                MethodAttributes.SpecialName Or
                                                MethodAttributes.HideBySig

        Dim propGet As MethodBuilder = BruceType.DefineMethod("get_Count", getMethodAttributes, GetType(Int32), Type.EmptyTypes)
        ' 讓方法可以設定與取得屬性值
        PropertyBL.SetGetMethod(propGet)

        ' 5. 建立型別
        Console.WriteLine("產生新型別")
        ' --- 註:建立型別之前要為所有 MethodBuilder 執行 GetILGenerator() ---
        ' --- 註:不然會產生一個「方法 'xxx' 沒有方法主體。」的錯誤,這裡 Debug 花了我好久!XD ---
        ' --- 註:參考:http://msdn.microsoft.com/zh-tw/library/system.reflection.emit.methodbuilder.definegenericparameters%28VS.85%29.aspx 範例才找出解法 ---
        Console.WriteLine(" 產生所有方法的ILGenerator")
        RunMethodBLGetILGenerator(MethodBLOne)
        RunMethodBLGetILGenerator(MethodBLTwo)
        RunMethodBLGetILGenerator(propGet)

        Console.Write(" 產生型別")
        Dim KKBruceType As Type = BruceType.CreateType()

        ' 5.1 顯示此型別方法
        Console.WriteLine()
        Console.WriteLine("     顯示型別方法(注意我們產生動態產生的方法)")
        GetRunTimeAssemblyMethods(KKBruceType)
        Console.WriteLine()
        Console.ReadLine()

        ' 6. 儲存組件到磁碟中
        Console.WriteLine("儲存組件到磁碟中...")
        ' 一但被寫入到磁碟中,任何程式都可以載入這個組件使用。
        AssemBL.Save(tempName.Name & ".dll")
        Console.WriteLine("儲存完成。(請參考專案目錄下「\bin\Debug」產生的動態組件 " & tempName.Name & ".dll")
        Console.ReadLine()
    End Sub

    ''' <summary>
    ''' 傳回這個方法的 ILGenerator
    ''' </summary>
    ''' <param name="methodInstance">MethodBuilder 的執行個體</param>
    ''' <remarks></remarks>
    Private Sub RunMethodBLGetILGenerator(methodInstance As MethodBuilder)
        ' MethodBuilder.GetILGenerator()
        ' 傳回這個方法的 ILGenerator,使用預設 Microsoft Intermediate Language (MSIL) 資料流的 64 位元大小。 
        Dim ilgen As ILGenerator = methodInstance.GetILGenerator()
        ilgen.Emit(OpCodes.Ldnull)
        ilgen.Emit(OpCodes.Ret)
    End Sub

    ''' <summary>
    ''' 取得動態組件方法屬性
    ''' </summary>
    ''' <param name="KKBruceType">型別</param>
    Private Sub GetRunTimeAssemblyMethods(ByVal KKBruceType As Type)
        Console.WriteLine("     Full Name: {0}", KKBruceType.FullName)
        For Each m As MemberInfo In KKBruceType.GetMethods()
            Console.WriteLine("         Member({0}):{1}", m.MemberType, m.Name)
        Next
    End Sub
#End Region

執行結果

執行環境中產生程式碼
定義組件
定義模組
定義型別
定義相關成員
     定義建構子
     定義方法
     定義私有欄位
     定義屬性
     定義方法中設得或設定屬性值
產生新型別
 產生所有方法的ILGenerator
 產生型別
     顯示型別方法(注意我們產生動態產生的方法)
     Full Name: KKBruceType
         Member(Method):AddStringOne
         Member(Method):AddStringTwo
         Member(Method):get_Count
         Member(Method):ToString
         Member(Method):Equals
         Member(Method):GetHashCode
         Member(Method):GetType


儲存組件到磁碟中...
儲存完成。(請參考專案目錄下「\bin\Debug」產生的動態組件 KKBruceSampleAssembly.dll

注意我們自行新增的 Method (AddStringOne, AddStringTwo, get_Count),確認一下產生的 DLL 檔:

圖一:儲存動態程式碼為組件

參考資料


下載 Reflection (1) ~ (9) 範例程式碼

感謝你們看到這九篇文章,我將第一篇至第九篇的範例整理成一個小小小小的 Console 選擇遊戲,以下是原始碼專案,必須使用 Visual Studio 2010 / .NET Framework 4 才能重新編譯。已編譯執行檔在 \bin\Debug\AssemblyDemo.exe,如果你想試試我前面介紹的 Reflection 工具,也可以從已編譯執行檔裡去看原始碼。



解壓縮密碼:KKBruce

此範例程式碼是「太濕版」一點也不「DRY, 乾」,全部用副程式在呼叫,下一篇我會將把此範例改寫為 OO (物件導向, Object-oriented) 的範例,算是大重構,不過從其中我們也能看到物件導向的優點,很多事你硬要使用「副程式/函式」來做是會…濕透了。

Visual Basic - Reflection, 反映教學筆記(8) 執行動態程式碼

在 Reflection (反映)中,支援不需要提前參考就可以從組件中動態地建立物件。我們可以動態去載入一個組件,不必事先 Import ( C# 中 using ),而且在組件中執行程式碼。

這一篇的內容比較複雜,要注意的地方我都寫成註解,所以我們直接來看相關副程式。我們先來看一個最簡單,也是一般在使用組件的方式。

UseHashtable 副程式

''' <summary>
''' 使用一般 Hashtable 方法來顯示
''' </summary>
Private Sub UseHashtable()
    Console.WriteLine("產生Hashtable")
    Dim tb As New Hashtable()
    tb.Add("Hi", "Hello")
    Console.WriteLine("Hash Count: {0}", tb.Count)
    Console.WriteLine()
    Console.ReadLine()
End Sub

UseHashtable 副程式執行結果

一般方式,使用Hashtable
產生Hashtable
Hash Count: 1

以上是很一般使用 Hashtable 的方式,沒有任何特別之處。但如果我們是要透過動態程式碼的方式來撰寫,就會複雜很多。

Visual Basic - Reflection, 反映教學筆記(7) - BindingFlags 過濾 Member(成員)

我們再談談Type 的 Member,我們前面寫過一段簡單取得 Member 的程式碼:

''' <summary>
''' 簡單測試及顯示型別 GetMembers() 方法
''' </summary>
''' <param name="type">型別 (即Type) 物件</param>
Private Sub ShowGetMembers(type As Type)
    Console.WriteLine("取得型別Members")
    For Each mi As MemberInfo In type.GetMembers()
        Console.WriteLine("    Member的 Type 及 名稱")
        Console.WriteLine("          {0}:{1}", mi.MemberType, mi.Name)
        ShowMemberType(mi)
    Next
    Console.WriteLine()
    Console.ReadLine()
End Sub

基本上,這沒什麼問題。但如果我想的資訊只需要「特定成員呢?」這時候我們就必須設定一個 BindingFlags 列舉型別給 type.GetMembers(),BindingFlags 指定控制繫結的旗標和由反映為引導的成員和型別搜尋方式。

這些 BindingFlags 會控制在叫用 (Invoke)、建立、取得、設定和尋找成員和型別的 System、System.Reflection 和 System.Runtime 命名空間中眾多類別的繫結。 

BindingFlags 用於下列 Type 方法和其他地方,例如,

  • MethodBase.Invoke
  • GetMembers 
  • GetEvents 
  • InvokeMember 
  • Activator.CreateInstance 
  • GetConstructor 
  • GetConstructors 
  • GetMethod 
  • GetMethods 
  • GetField 
  • GetFields 
  • GetEvent 
  • GetProperty 
  • GetProperties 
  • GetMember 
  • FindMembers 

其中 InvokeMember 和 GetMethod 特別重要。

Visual Basic - Reflection, 反映教學筆記(6) 暸解MethodBody

前面幾篇,我們可以透過型別、型別成員…等去瞭解型別的結果,但還是無法瞭解型別包含的程式碼,這時就可以透過 MethodBody 來瞭解。MethodBody 是一個特殊的物件,裝載著區域變數及實際中介語言( Intermediate Language;IL )。

在開始以下範例前,我們先進行一個準備工作。我們先從 MSDN 複製一個範例 Class 到我們的主程式碼的最下方。

#Region "MSDN中 MethodBase.GetMethodBody 方法範例"
''' <summary>
''' From MSDN: MethodBase.GetMethodBody 方法範例
''' http://msdn.microsoft.com/zh-tw/library/system.reflection.methodbody.aspx
''' </summary>
Public Class Example
    Public Shared Sub Main()
        ' 請從 MSDN 複製
    End Sub
End Class
#End Region

因為等一會的程式,必須從一個 Class 取得型別,從型別裡取得 MethodInfo ,再從 MethodInfo 取得 MethodBody,最後就能從 MethodBody 得到我們想要的資訊。

Visual Basic - Reflection, 反映教學筆記(5) 取得型別相關屬性

我們在上一篇「Visual Basic - Reflection, 反映教學筆記(4) 取得型別的4種方法」中,在 Object 取得型別裡,給了一段不算短的程式碼,主要是顯示別型相關訊息。這一篇主要解釋那一段程式碼。此副程式的主要進入點為 ShowTypeAttributes()。

ShowTypeAttributes 副程式

''' <summary>
''' 直接顯示型別相關資訊
''' </summary>
Sub ShowTypeAttributes()
    Dim type As Type = GetType(String)
    ' 取得型別屬性
    GetTypeAttribute(type)
    ' 取得型別自訂屬性
    ShowCustomAttribute(type)
    ' 取得型別 Getxxx 
    ShowTypeGetxxx(type)
End Sub

這裡很簡單,只是取得型別後,我想顯示一些型別的屬性、方法。我把這些方法另外再分為三個小副程式。

Visual Basic - Reflection, 反映教學筆記(4) 取得型別的4種方法

前面,我們已經學會了從組件(Assembly)、模組(Module)取得資訊,也試著從 AssemblyInfo.vb 取得屬性。還有那一句超重點:「組件(Assembly)包含模組(Module),模組包含型別(Type),型別包含成員。」今天我們進行第三個重點,型別(Type),進入之前,我們先看一點點 MSDN 的資料。
System.Type 類別 代表型別宣告:類別型別、介面型別、陣列型別、值型別、列舉型別、型別參數、泛型型別定義,以及開放式或封閉式的建構泛型型別。
…最下面的備註…
Type 是 System.Reflection 功能的,也是存取中繼資料 (Metadata) 的主要方法。 使用 Type 的成員以取得型別宣告的資訊,例如建構函式 (Constructor)、方法、欄位、屬性和類別的事件,以及模組和部署類別的組件。 C# typeof 運算子 (在 Visual Basic 中為 GetType 運算子,在 Visual C++ 中則為 typeid 運算子) 會傳回 Type 物件。 Type 物件表示型別是唯一的;也就是兩個 Type 物件參考只有在它們表示相同型別時才會參考相同物件。 如此就允許使用參考的相等來比較 Type 物件。…

System.Type 類別簡易介紹

透過 MSDN,我們知道,了解 Reflection 時也必須一併了解 System.Type 類別,不過 System.Type 類別是個大類別,當我看完那長長一列的屬性與方法後,頭也昏的。

System.Type 類別的屬性與方法

其實沒那麼複雜,就 Type 屬性或方法而言,基本上分成兩大類,
  1. Getxxx:Get 開頭為一類
  2. Isxxx:Is 開頭為一類
Getxxx 所代表的是「取得」,取得此型別(Type)的 xxx,從建構函式、自訂屬性、公用欄位、介面、公用成員、公用方法、公用屬性 …。反正你想得到的一切,Getxxx 都能幫你取得。

Isxxx 所代表的是「判斷」,你能拿 Isxxx 來判斷此型別(Type),例如,Type.IsArray() 判斷是否為陣列。

當我們取得型別(Type)後,我們就能夠透過 Getxxx 或 Isxxx 來取得與判斷此型別。所以,回過頭來,我們要來介紹,取得取得型別的4種方法。

Visual Basic - Reflection, 反映教學筆記(3) 取得特定屬性

前一篇「Visual Basic - Reflection, 反映教學筆記(2) 基礎反映了解」我們學習取得 Assembly, Module 的資訊,這一篇我們來學習取得「取得Assembly特定屬性」。

其實我們開一個網站專案也好,或是主控台專案也好,開發工具會幫我們預設許多屬性,以我們主控台專案為例,我們先按「顯示所有檔案」,然後在「My Project」下可以找到一個 AssemblyInfo.vb 檔案,預設都是 Microsoft ...的內容,以下是我修改後的內容。

Imports System.Resources

Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices

' 組件的一般資訊是由下列的屬性集控制。
' 變更這些屬性的值即可修改組件的相關
' 資訊。

' 檢閱組件屬性的值

<Assembly: AssemblyTitle("AssemblyDemo")> 
<Assembly: AssemblyDescription("This is KKBruce Assembly Test and Study.")> 
<Assembly: AssemblyCompany("KKBruce")> 
<Assembly: AssemblyProduct("AssemblyDemo")> 
<Assembly: AssemblyCopyright("Copyright KKBruce 2011")> 
<Assembly: AssemblyTrademark("KKBruce")> 
<Assembly: AssemblyFlags(AssemblyNameFlags.EnableJITcompileOptimizer or Reflection.AssemblyNameFlags.EnableJITcompileTracking )>

<Assembly: ComVisible(False)>

'下列 GUID 為專案公開 (Expose) 至 COM 時所要使用的 typelib ID
<Assembly: Guid("e62bb460-650f-47f7-9b2f-e0aae99fccfb")> 

' 組件的版本資訊是由下列四項值構成:
'
'      主要版本
'      次要版本
'      組建編號
'      修訂編號
'
' 您可以指定所有的值,也可以依照以下的方式,使用 '*' 將組建和修訂編號
' 指定為預設值:
' <Assembly: AssemblyVersion("1.0.*")> 

<Assembly: AssemblyVersion("1.0.0.0")> 
<Assembly: AssemblyFileVersion("1.0.0.0")> 

<assembly: NeutralResourcesLanguageAttribute("zh-TW")>

接下來,我們要透過 Reflection 來取得此 AssemblyInfo.vb 檔案內容裡的資訊。

Visual Basic - Reflection, 反映教學筆記(2) 基礎反映了解

基礎反映了解

反映( Reflection )主要是用於檢測型別,讓你可以取得已載入的組件(*.dll)及組件中所定義型別的相關資料。

組件(Assembly)包含模組(Module),模組包含型別(Type),型別包含成員。使用反映( Reflection )可以如「動態建立型別執行個體、繫結型別至現有物件、從現有物件取得型別…等。接著叫用型別的方法、存取屬性、存取欄位」等。

舉例,如果我們開發一個 Mvc3GuestbookVB 網站,編譯後,會在 網站 \bin 目錄下產生相關的 DLL組件檔案,

圖一、Mvc 網站編譯輯產生的組件(對擊看大圖)
裡面的 *.dll 都是組件,組件包含了所有執行的必要資訊,由於.NET Framework是在 CLR 環境執行,所以我們都能透過 Reflection 去看組件中所有資訊。例如,我們使用 Telerik JustDecompile (目前免費) 解析工具,去解析其中的 Mvc3GuestbookVB04.dll 組件。

圖二:使用 Telerik JustDecomplile 解析組件(對擊看大圖)
又例如,我們這個學習Reflection的範例,是寫成「Console 主控台」專案,編譯後是一個 AssemblyDemo.exe 執行檔,一樣可以使用 Reflection 去取得相關資訊,例如,

圖三:解析 Console AssemblyDemo.exe(對擊看大圖)

那我寫的.NET Framework程式碼不就被看光光?基本上,是的。沒辦法,這是 Microsoft Intermediate Language (MSIL) 的特性。所以市面上有賣「程式干擾器」,類似 Google Closure Compiler原理,把程式搞的亂七八糟,但是能正常執行,當我去 Reflection 時,增加"人"閱讀的難度。不過前提是,他要能拿得到你那編譯好的組件檔。不過就我了解,價格都不太便宜。

我去聽課時,一些講師很喜歡用類似 Telerik JustDecompile 工具去看 .NET Framework 裡 DLL 的Source Code,那時候覺得他們好神!聽他們說,這樣能更了解更底層的內容,也間接幫助記憶與了解此類別,因為有時連 MSDN 都交代的不清不楚。例如,我們想更了解 Entity Framework 4.1的內容,那我們就可以去下載 EntityFramework.dll,

圖四:解析 EntityFramework 4.1 DbContext(對擊看大圖)
想看什麼就看什麼,從 Source Code 我們能看光光每個組件的內容。我們先從簡單的取得 Assembly 基本資訊,然後介紹再取得 Module 基本資訊。

Visual Basic - Reflection, 反映教學筆記(1) 前言

我的VB學習史

我知道,C#是後起之秀,但支持者之多,讓我們這些使用VB的人都有…不爽吧!姑且不論,但我發現一件更不爽的事。先說說我的VB歷史吧。從 DOS 6.22 開始,第一次接觸到 Basic 程式語言,後來大學接觸到有GUI的 VB6,最後跑去寫 ASPNET Framework 1.x 與 ASP.NET 1.x 中斷學習,老實說,那時候的 .NET Framework 與 ASP.NET,我有嘗試去學習,但最後放棄了,這故事在「關於.NET Framework / ASP.NET這條路」已經說過。 

現在,我又碰到新的問題,那時ASP使用的好好的,所以我的Know-How都停在VB6,後來我為了學 ASP.NET 2.0,還特定去買了 Visual Basic 2008 的書回來學習,Renew - Re-Study 一下我 Visual Basic 相關 Knowledge。但各位長輩們也知道,除非是像 MSDN 這種佛心級的資源文件,不然,你要找個資料、學個東西,有很大一部份你都會看到 C# 語法的內容。 平常的 C# 轉 VB,我是還沒有什麼問題,後來在論壇上請教前輩時,學到了一個網站 developerfusion ,可以讓我們把 C# 轉 VB 語法,他網站有註明只支持到 .NET 3.5 語法,不過就我使用而言,到沒碰過什麼很特別的語法轉換不出來的。 

我碰到的新問題是,就算轉換成 Visual Basic 也看不懂的內容?Try the VB Code,這些 Code 都能動,程式都很正常。是我不用功嗎?這些是什麼 Code,標題寫的很清楚了「Reflection,反映」。想說,好吧,是我們自己不用功,那去找本書來看,在上網看了一下 Visual Baisc 2010 各書籍的目錄,結果讓人吃驚。 

資訊安全 - MSN帳號被盜

同事MSN帳號被盜,結果只能看著盜者跟朋友對話。

Je 說:

www.wryochnncnwblog.in

^^來看我的部落格幫我衝衝人氣^^

Ja 說:

好

Je 說:

在嗎

Ja 說:

在

你不是下班了

Je 說:

嗯嗯

我現在用筆電

Ja 說:

東西忘了拿嗎

Je 說:

你還沒有下班嗎

Ja 說:

嗯

還在公司寫報告

Je 說:

可以幫我個忙嗎

Ja 說:

可以

Je 說:

可以幫我買幾張MY CRAD卡嗎

Ja 說:

這是什麼東東

Je 說:

儲值用的 

你和店員說買儲值用的MY CARD卡他們就瞭解啦

7 11 全家有買的

Ja 說:

買幾張

Je 說:

幫我買4張面額1000的

Ja 說:

鬼撞牆之IE, Chrome, Firefox無法連上MSDN (4) 之重現MSDN錯誤訊息

依以下步驟,在任一瀏覽器,我能不斷重現 MSDN 網頁的錯誤。

如果你已經產生錯誤,請先依前面教學,刪除 Microsoft.com 此一問題 Cookie,先回復到沒有問題的狀態。然後,我們要讓 MSDN 的錯誤,再次出現。

  1. 進入 MSDN 文件首頁
  2. 搜尋任一關鍵字,例如,搜尋 reflection or list
  3. 點擊任何連結 --> Bing Go
圖一:使用 Bing 搜尋 MSDN
透過「搜尋」功能後,就能讓你的 MSDN 重顯「The specified CGI application encountered an error and the server terminated the process.」錯誤訊息,而且現在你應該是任何 MSDN 文件網頁都無法瀏覽了

其實,在 Step 2 問題就已經重現了,你可以搜尋之後,按「書籤」裡的連結,或是輸入:http://msdn.microsoft.com/,你就能發現,已經無法瀏覽 MSDN 網站。

有興趣的人,就能依此步驟拿到有問題的Cookie,如果你想研究研究的話。(它(機碼 Microsoft.com )只是暫存我們搜尋的網址,也沒有什麼重要的內容!)@_@

參考:

鬼撞牆之IE, Chrome, Firefox無法連上MSDN (3) 之問題Cookie

實在不好意思,假日我是一位超奶(超級奶爸),實在只能利用寶貝們上床的時間,來進行這個「鬼撞牆」任務。也好,將每個任務切小小的,一步步追的過程,到不像那種「幾個字,花幾小時」那種經驗的辛苦。

不過,心裡一直掛念著,到是真的。

回首鬼撞牆


我在「鬼撞牆(1)」出事,但也亂搞出一個解決辦法,也得到是因為 Cookie 造成 MSDN 錯誤,但沒留下任何蛛絲馬跡。在「鬼撞牆(2)」也就第二天,又再次出事,而且這次連第一天能正常連線的 Firefox 也無法正常運作,但也拜問題重顯之福,這次我小心翼翼把玩這 IE, Chrome, Firefox 裡的 Cookie,最後終於讓我找到有問題源頭 Cookie。

以下是有問題 Cookie 的XML檔,From IE F12 開發者工具:
<?xml version="1.0" encoding="UTF-8"?>
<log>
	<version>1.1</version>
	<creator>
		<name>Internet Explorer 網路檢查</name>
		<version>9.0.8112.16421</version>
	</creator>
	<browser>
		<name>Internet Explorer</name>
		<version>9.0.8112.16421</version>
	</browser>
	<pages>
		<page>
			<startedDateTime>2011-09-04T13:34:51.695+08:00</startedDateTime>
			<id>0</id>
			<title/>
			<pageTimings>
				<onContentLoad>227</onContentLoad>
				<onLoad>238</onLoad>
			</pageTimings>
		</page>
	</pages>
	<entries>
		<entry>
			<pageref>0</pageref>
			<startedDateTime>2011-09-04T13:34:51.695+08:00</startedDateTime>
			<time>187</time>
			<request>
				<method>GET</method>
				<url>http://msdn.microsoft.com/</url>
				<httpVersion>HTTP/1.1</httpVersion>
				<cookies>
					<cookie>
						<name>TocHashCookie</name>
						<value>ms310241(n)/</value>
					</cookie>
					<cookie>
						<name>WT_NVR</name>
						<value>0=/:1=zh-tw|library:2=zh-tw/library:3=zh-tw/library/community</value>
					</cookie>
					<cookie>
						<name>A</name>
						<value>I&amp;I=AxUFAAAAAAChBwAANNr2/wpKagArfkiaPMsnCg!!&amp;M=1</value>
					</cookie>
					<cookie>
						<name>omniID</name>
						<value>1315124990139_6d2f_5340_cefd_9babfa8cc553</value>
					</cookie>
					<cookie>
						<name>WT_FPC</name>
						<value>id=123.195.36.172-230651568.30156417:lv=1315068214015:ss=1315067390233</value>
					</cookie>
					<cookie>
						<name>WT_NVR_RU</name>
						<value>0=msdn:1=:2=</value>
					</cookie>
					<cookie>
						<name>msdn</name>
						<value>L=1028</value>
					</cookie>
					<cookie>
						<name>Microsoft.com</name>
						<value>SS=1&amp;SS_Refn=0&amp;SS_Url=http://social.msdn.microsoft.com/Search/zh-tw?query=cg&amp;x=0&amp;y=0~~2011/9/4 �� 08:43:07</value>
					</cookie>
					<cookie>
						<name>MUID</name>
						<value>BC2FDEB409EB4230B987BCDF6A394146</value>
					</cookie>
					<cookie>
						<name>MSID</name>
						<value>Microsoft.CreationDate=09/04/2011 08:43:09&amp;Microsoft.LastVisitDate=09/04/2011 08:43:28&amp;Microsoft.VisitStartDate=09/04/2011 08:43:09&amp;Microsoft.CookieId=ea95f0a2-d7b6-4f08-baea-3d683e4148a8&amp;Microsoft.TokenId=ffffffff-ffff-ffff-ffff-ffffffffffff&amp;Microsoft.NumberOfVisits=3&amp;Microsoft.CookieFirstVisit=1&amp;Microsoft.IdentityToken=AA==&amp;Microsoft.MicrosoftId=0102-2054-3786-4152</value>
					</cookie>
					<cookie>
						<name>MC1</name>
						<value>GUID=afc3a69a2c9a6349a2f3679acf03f697&amp;HASH=9aa6&amp;LV=20119&amp;V=3</value>
					</cookie>
					<cookie>
						<name>ADS</name>
						<value>SN=175A21EF</value>
					</cookie>
				</cookies>
				<headers>
					<header>
						<name>Accept</name>
						<value>text/html, application/xhtml+xml, */*</value>
					</header>
					<header>
						<name>Accept-Language</name>
						<value>zh-TW</value>
					</header>
					<header>
						<name>User-Agent</name>
						<value>Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)</value>
					</header>
					<header>
						<name>Accept-Encoding</name>
						<value>gzip, deflate</value>
					</header>
					<header>
						<name>Host</name>
						<value>msdn.microsoft.com</value>
					</header>
					<header>
						<name>Connection</name>
						<value>Keep-Alive</value>
					</header>
					<header>
						<name>Cache-Control</name>
						<value>no-cache</value>
					</header>
					<header>
						<name>Cookie</name>
						<value>TocHashCookie=ms310241(n)/; WT_NVR=0=/:1=zh-tw|library:2=zh-tw/library:3=zh-tw/library/community; A=I&amp;I=AxUFAAAAAAChBwAANNr2/wpKagArfkiaPMsnCg!!&amp;M=1; omniID=1315124990139_6d2f_5340_cefd_9babfa8cc553; WT_FPC=id=123.195.36.172-230651568.30156417:lv=1315068214015:ss=1315067390233; WT_NVR_RU=0=msdn:1=:2=; msdn=L=1028; Microsoft.com=SS=1&amp;SS_Refn=0&amp;SS_Url=http://social.msdn.microsoft.com/Search/zh-tw?query=cg&amp;x=0&amp;y=0~~2011/9/4 �� 08:43:07; MUID=BC2FDEB409EB4230B987BCDF6A394146; MSID=Microsoft.CreationDate=09/04/2011 08:43:09&amp;Microsoft.LastVisitDate=09/04/2011 08:43:28&amp;Microsoft.VisitStartDate=09/04/2011 08:43:09&amp;Microsoft.CookieId=ea95f0a2-d7b6-4f08-baea-3d683e4148a8&amp;Microsoft.TokenId=ffffffff-ffff-ffff-ffff-ffffffffffff&amp;Microsoft.NumberOfVisits=3&amp;Microsoft.CookieFirstVisit=1&amp;Microsoft.IdentityToken=AA==&amp;Microsoft.MicrosoftId=0102-2054-3786-4152; MC1=GUID=afc3a69a2c9a6349a2f3679acf03f697&amp;HASH=9aa6&amp;LV=20119&amp;V=3; ADS=SN=175A21EF</value>
					</header>
				</headers>
				<queryString/>
				<headersSize>1228</headersSize>
				<bodySize>0</bodySize>
			</request>
			<response>
				<status>502</status>
				<statusText>Bad Gateway</statusText>
				<httpVersion>HTTP/1.1</httpVersion>
				<cookies/>
				<headers>
					<header>
						<name>Content-Type</name>
						<value>text/html</value>
					</header>
					<header>
						<name>Location</name>
						<value>http://msdn.microsoft.com/zh-tw/default.aspx</value>
					</header>
					<header>
						<name>Server</name>
						<value>Microsoft-IIS/7.5</value>
					</header>
					<header>
						<name>P3P</name>
						<value>CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI"</value>
					</header>
					<header>
						<name>X-Powered-By</name>
						<value>ASP.NET</value>
					</header>
					<header>
						<name>Date</name>
						<value>Sun, 04 Sep 2011 13:34:43 GMT</value>
					</header>
					<header>
						<name>Content-Length</name>
						<value>89</value>
					</header>
				</headers>
				<content>
					<size>89</size>
					<mimeType>text/html</mimeType>
					<text>The specified CGI application encountered an error and the server terminated the process.</text>
				</content>
				<redirectionURL/>
				<headersSize>333</headersSize>
				<bodySize>89</bodySize>
			</response>
			<cache/>
			<timings>
				<send>0</send>
				<wait>187</wait>
				<receive>0</receive>
			</timings>
		</entry>
	</entries>
</log>

鬼撞牆之IE, Chrome, Firefox無法連上MSDN (2)

我發現我的第一篇「鬼撞牆之IE, Chrome無法連上MSDN」很快就開始救人了。而且發現,Search此錯誤訊息而到我 Blog 的人也多了起來。

 今天更發現,連 Firefox 也逃不過此 MSDN 錯誤訊息:「The specified CGI application encountered an error and the server terminated the process.」,MSDN 的災情擴大了。

圖一:Firefox with MSDN CGI error message (點小圖看大圖)
而且,這一次發生時,連原本的 IE, Chrome 都再一次重覆中獎。這也讓我可以抓個Cookie的圖片,補上前一篇沒抓到 Cookie 任何資料的遺憾。

圖二:IE 產生 CGI 時的 Cookie 狀態 (圖小圖看大圖) 
圖三:IE 使用 F12 開發者工具清除 Cookie後,重新連線後的 Cookie (點小圖看大圖)
不過,此次清除後。我在點擊沒幾頁後,馬上就再出現此 CGI 錯誤,也有很大的機會是「下一頁」馬上中獎。

我只能望天而問:MSDN 你怎麼了???

參考:

鬼撞牆之IE, Chrome無法連上MSDN

假日,趁著孩子還在睡覺,打開電腦上一下網。想要回答一位網友的問題,想到 MSDN 找連結,以讓網友可以自行參考資料,進而解決問題。

但沒想到,一開 MSDN 就出事。我連開 Chrome, IE 都是一樣的問題,出現一個錯誤訊息:「The specified CGI application encountered an error and the server terminated the process.」

圖一:Chrome 無法連線 MSDN

圖二、IE 無法連線 MSDN
本來想說,是不是 MSDN 知道我們的辛苦,假日會很 AI 的讓我們休息。後來到 Plurk 去發個文,想不到小朱大大馬上回應說:「很正常」。我去清 IE 的快取,重新連,一樣的錯誤!接著打開我的第三個瀏覽器 Firefox,很好,見鬼了,Firefox 可以很正常連線。

金剛事件簿 - 那些年我們當過程式設計師

如果你願意,請好好了解我們。我們是人不是神愛我,請好好了解我們

這部 22:56 min 的片了,能讓你了解「何謂程式設計師」。而且片中男主角是我們鼎鼎大名的MVP,如何你常去點部落,就能常看到他的分享。

不多說,我們看片子吧,片名我取為:那些年我們當過程式設計師。(有沒有人有二千萬,請九把刀為我們這些爆肝人也拍一片)

  
轉貼 - 100年職場達人SHOW-程式設計師

同場加映:那些年,我們一起追的女孩


ps.. "那些年,我們一起追的女孩",實在太紅了。(誰能幫我顧小孩,我好想去看場電影,哭ing,我不想只能預告片)

OOP - 學習資源補充資料

這是由在 Plurk 看到其他大大提供的 OOP 資料的Link,我覺得很棒,所以整理一下。

哇!哇!哇!
太棒了!

金剛事件簿 - 什麼是好朋友

我有一位弟弟,是我在經營組織事業時認識的。那時的他,大三左右,後來,組織發生了很多事,我們解散了,他可以說是非常非常少數還有在連絡的人(二人的其中一人)。

經過多年相處,我和婆婆對他跟對待弟弟沒什麼差異。人就是那麼怪,是感覺嗎?是緣份嗎?

這週,我這位弟弟又打來一通電話說:
弟弟:Bruce我電腦開不了機,可以幫我看一下嗎?
我:哦,費用我會算在我二個女兒的學費裡。載來吧!
弟弟:…我知道,我會努力的。…
… 場景切換到我家 …