逐步解說:從 Managed 組件內嵌類型 (C# 和 Visual Basic)
如果您內嵌來自 Managed 強式名稱組件的型別資訊,就可以寬鬆地配合應用程式中的型別來達到版本獨立的目的。 也就是說,撰寫程式時,可以讓它使用來自多個 Managed 程式庫版本的型別,而不必為每個版本重新編譯。
型別內嵌經常與 COM Interop 搭配使用,例如使用 Microsoft Office 之 Automation 物件的應用程式。 內嵌型別資訊讓程式的相同組建可以在不同電腦上使用不同版本的 Microsoft Office。 但是您也可以搭配完整的 Managed 方案使用型別內嵌。
您可以從具有下列特性的組件來內嵌資訊:
組件公開了至少一個公用介面。
內嵌的介面已使用 ComImport 屬性和 Guid 屬性 (及唯一的 GUID) 來標註。
組件已使用 ImportedFromTypeLib 屬性或 PrimaryInteropAssembly 屬性以及組件層級的 Guid 屬性來標註。 (根據預設,Visual Basic 和 Visual C# 專案範本包含組件層級的 Guid 屬性)。
在指定可以內嵌的公用介面之後,您可以建立實作這些介面的執行階段類別。 接著,用戶端程式便可以參考包含公用介面的組件並將參考的 Embed Interop Types 屬性設定為 True,以在設計階段內嵌這些介面的型別資訊。 這相當於使用 /link 編譯器選項來使用命令列編譯器和參考組件。 然後,用戶端程式可以載入以這些介面為型別之執行階段物件的執行個體。 如果您建立新版的強式名稱執行階段組件,並不需要以更新的執行階段組件重新編譯用戶端程式。 相反地,用戶端程式會使用公用介面的內嵌型別資訊,繼續使用任何可用的執行階段組件版本。
由於型別內嵌的主要功能是支援內嵌來自 COM Interop 組件中的型別資訊,因此當您內嵌完整 Managed 方案中的型別資訊時,必須注意下列限制:
只有 COM Interop 特有的屬性會內嵌,其他屬性會遭忽略。
如果有某個型別使用泛型參數,而該泛型參數的型別為內嵌的型別,則該型別無法超出組件範圍來使用。 超出組件範圍使用的例子,包括呼叫來自其他組件中的方法,或從其他組件中所定義的型別衍生另一個型別。
常數不會內嵌。
Dictionary 類別不支援以內嵌的型別做為索引鍵。 您可以實作您自己的字典型別,以支援以內嵌的型別做為索引鍵。
在這個逐步解說中,您將執行下列工作:
建立具有公用介面的強式名稱組件,這個介面內含可內嵌的型別資訊。
建立實作公用介面的強式名稱執行階段組件。
建立內嵌公用介面之型別資訊的用戶端程式,並從執行階段組件建立類別的執行個體。
修改並重新建置執行階段組件。
執行用戶端程式以查看是否正在使用新版的執行階段組件,而不必重新編譯用戶端程式。
注意事項 |
---|
您的電腦對於下列指示中某些 Visual Studio 使用者介面項目的名稱或位置,可能會顯示不同的資訊:您所擁有的 Visual Studio 版本以及使用的設定會決定這些項目。如需詳細資訊,請參閱<Visual Studio 中的自訂開發設定>。 |
建立介面
若要建立型別等價介面專案
在 Visual Studio 中的 [檔案] 功能表上,指向 [新增] 然後按一下 [專案]。
在 [新增專案] 對話方塊的 [專案類型] 窗格中,確定已選取 [Windows]。 選取 [範本] 窗格中的 [類別庫]。 在 [名稱] 方塊中輸入 TypeEquivalenceInterface,然後按一下 [確定]。 接著會建立新專案。
在 [方案總管] 中,以滑鼠右鍵按一下 Class1.vb 或 Class1.cs 檔,然後按一下 [重新命名]。 將檔案重新命名為 ISampleInterface.vb 或 ISampleInterface.cs,並按下 ENTER。 重新命名檔案時也會將類別重新命名為 ISampleInterface。 這個類別將會代表類別的公用介面。
以滑鼠右鍵按一下 [TypeEquivalenceInterface] 專案,然後按一下 [屬性]。 在 Visual Basic 中按一下 [編譯] 索引標籤,在 Visual C# 中則按一下 [建置] 索引標籤。 將輸出路徑設定為開發電腦上的有效位置,例如 C:\TypeEquivalenceSample。 在本逐步解說的稍後步驟中也會用到這個位置。
當您還在編輯專案屬性時,按一下 [簽署] 索引標籤。 選取 [簽署組件] 選項。 在 [選擇強式名稱金鑰檔] 清單中,按一下 [<新增>]。 在 [金鑰檔名稱] 方塊中,輸入 key.snk。 清除 [以密碼保護我的金鑰檔] 核取方塊。 按一下 [確定]。
開啟 ISampleInterface.vb 或 ISampleInterface.cs 檔。 將下列程式碼加入至 ISampleInterface 類別檔案,以建立 ISampleInterface 介面。
Imports System.Runtime.InteropServices <ComImport()> <Guid("8DA56996-A151-4136-B474-32784559F6DF")> Public Interface ISampleInterface Sub GetUserInput() ReadOnly Property UserInput As String ... End Interface
using System; using System.Runtime.InteropServices; namespace TypeEquivalenceInterface { [ComImport] [Guid("8DA56996-A151-4136-B474-32784559F6DF")] public interface ISampleInterface { void GetUserInput(); string UserInput { get; } ... } }
在 [工具] 功能表上按一下 [建立 GUID]。 在 [建立 GUID] 對話方塊中,按一下 [登錄格式],再按一下 [複製]。 按一下 [結束]。
在 Guid 屬性中刪除範例 GUID,並貼上您從 [建立 GUID] 對話方塊複製的 GUID。 從複製的 GUID 移除大括號 ({})。
在 Visual Basic 中,按一下 [專案] 功能表上的 [顯示所有檔案]。 如果您使用 Visual C#,請跳過這個步驟。
如果您是使用 Visual Basic,請在 [方案總管] 中展開 [我的專案] 資料夾。 如果是使用 Visual C#,則展開 [屬性] 資料夾。 按兩下[ AssemblyInfo.vb] 或 [AssemblyInfo.cs] 檔, 將下列屬性加入至檔案。
<Assembly: ImportedFromTypeLib("")>
[assembly: ImportedFromTypeLib("")]
儲存檔案。
儲存專案。
以用滑鼠右鍵按一下 [TypeEquivalenceInterface] 專案,然後按一下 [建置]。 類別庫 .dll 檔隨即進行編譯,並儲存至指定的建置輸出路徑 (例如,C:\TypeEquivalenceSample)。
建立執行階段類別
若要建立型別等價執行階段專案
在 Visual Studio 中的 [檔案] 功能表上,指向 [新增] 然後按一下 [專案]。
在 [新增專案] 對話方塊的 [專案類型] 窗格中,確定已選取 [Windows]。 選取 [範本] 窗格中的 [類別庫]。 在 [名稱] 方塊中輸入 TypeEquivalenceRuntime,然後按一下 [確定]。 接著會建立新專案。
在 [方案總管] 中,以滑鼠右鍵按一下 Class1.vb 或 Class1.cs 檔,然後按一下 [重新命名]。 將檔案重新命名為 SampleClass.vb 或 SampleClass.cs,並按下 ENTER。 重新命名檔案時也會將類別重新命名為 SampleClass。 這個類別會實作 ISampleInterface 介面。
以滑鼠右鍵按一下 [TypeEquivalenceRuntime] 專案,然後按一下 [屬性]。 在 Visual Basic 中按一下 [編譯] 索引標籤,在 Visual C# 中則按一下 [建置] 索引標籤。 將輸出路徑設定為您在 TypeEquivalenceInterface 專案中使用的同樣位置,例如 C:\TypeEquivalenceSample。
當您還在編輯專案屬性時,按一下 [簽署] 索引標籤。 選取 [簽署組件] 選項。 在 [選擇強式名稱金鑰檔] 清單中,按一下 [<新增>]。 在 [金鑰檔名稱] 方塊中,輸入 key.snk。 清除 [以密碼保護我的金鑰檔] 核取方塊。 按一下 [確定]。
以滑鼠右鍵按一下 [TypeEquivalenceRuntime] 專案,然後按一下 [加入參考]。 按一下 [瀏覽] 索引標籤,然後瀏覽至輸出路徑資料夾。 選取 [TypeEquivalenceInterface.dll] 檔案,然後按一下 [確定]。
在 Visual Basic 中,按一下 [專案] 功能表上的 [顯示所有檔案]。 如果您使用 Visual C#,請跳過這個步驟。
在 [方案總管] 中,展開 [參考] 資料夾。 選取 [TypeEquivalenceInterface] 參考。 在 [TypeEquivalenceInterface] 參考的 [屬性] 視窗中,將 [特定版本] 屬性設定為 [False]。
將下列程式碼加入至 SampleClass 類別檔案,以建立 SampleClass 類別。
Imports TypeEquivalenceInterface Public Class SampleClass Implements ISampleInterface Private p_UserInput As String Public ReadOnly Property UserInput() As String Implements ISampleInterface.UserInput Get Return p_UserInput End Get End Property Public Sub GetUserInput() Implements ISampleInterface.GetUserInput Console.WriteLine("Please enter a value:") p_UserInput = Console.ReadLine() End Sub ... End Class
using System; using System.Collections.Generic; using System.Linq; using System.Text; using TypeEquivalenceInterface; namespace TypeEquivalenceRuntime { public class SampleClass : ISampleInterface { private string p_UserInput; public string UserInput { get { return p_UserInput; } } public void GetUserInput() { Console.WriteLine("Please enter a value:"); p_UserInput = Console.ReadLine(); } ... } }
儲存專案。
以滑鼠右鍵按一下 [TypeEquivalenceRuntime] 專案,然後按一下 [建置]。 類別庫 .dll 檔隨即進行編譯,並儲存至指定的建置輸出路徑 (例如,C:\TypeEquivalenceSample)。
建立用戶端專案
若要建立型別等價用戶端專案
在 Visual Studio 中的 [檔案] 功能表上,指向 [新增] 然後按一下 [專案]。
在 [新增專案] 對話方塊的 [專案類型] 窗格中,確定已選取 [Windows]。 選取 [主控台應用程式] 中的 [範本] 窗格。 在 [名稱] 方塊中輸入 TypeEquivalenceClient,然後按一下 [確定]。 接著會建立新專案。
以滑鼠右鍵按一下 [TypeEquivalenceClient] 專案,然後按一下 [屬性]。 在 Visual Basic 中按一下 [編譯] 索引標籤,在 Visual C# 中則按一下 [建置] 索引標籤。 將輸出路徑設定為您在 TypeEquivalenceInterface 專案中使用的同樣位置,例如 C:\TypeEquivalenceSample。
以滑鼠右鍵按一下 [TypeEquivalenceClient] 專案,然後按一下 [加入參考]。 按一下 [瀏覽] 索引標籤,然後瀏覽至輸出路徑資料夾。 選取 [TypeEquivalenceInterface.dll] (而非 [TypeEquivalenceRuntime.dll]) 檔案,然後按一下 [確定]。
在 Visual Basic 中,按一下 [專案] 功能表上的 [顯示所有檔案]。 如果您使用 Visual C#,請跳過這個步驟。
在 [方案總管] 中,展開 [參考] 資料夾。 選取 [TypeEquivalenceInterface] 參考。 在 [TypeEquivalenceInterface] 參考的 [屬性] 視窗中,將 [內嵌 Interop 型別] 屬性設定為 [True]。
將下列程式碼加入至 Module1.vb 或 Program.cs 檔案,以建立用戶端程式。
Imports TypeEquivalenceInterface Imports System.Reflection Module Module1 Sub Main() Dim sampleAssembly = Assembly.Load("TypeEquivalenceRuntime") Dim sampleClass As ISampleInterface = CType( _ sampleAssembly.CreateInstance("TypeEquivalenceRuntime.SampleClass"), ISampleInterface) sampleClass.GetUserInput() Console.WriteLine(sampleClass.UserInput) Console.WriteLine(sampleAssembly.GetName().Version) Console.ReadLine() End Sub End Module
using System; using System.Collections.Generic; using System.Linq; using System.Text; using TypeEquivalenceInterface; using System.Reflection; namespace TypeEquivalenceClient { class Program { static void Main(string[] args) { Assembly sampleAssembly = Assembly.Load("TypeEquivalenceRuntime"); ISampleInterface sampleClass = (ISampleInterface)sampleAssembly.CreateInstance("TypeEquivalenceRuntime.SampleClass"); sampleClass.GetUserInput(); Console.WriteLine(sampleClass.UserInput); Console.WriteLine(sampleAssembly.GetName().Version.ToString()); Console.ReadLine(); } } }
按 CTRL+F5 建置和執行程式。
修改介面
若要修改介面
在 Visual Studio 的 [檔案] 功能表上,指向 [開啟],再按一下 [專案/方案]。
在 [開啟專案] 對話方塊中,以滑鼠右鍵按一下 [TypeEquivalenceInterface] 專案,然後按一下 [屬性]。 按一下 [應用程式] 索引標籤。 按一下 [組件資訊] 按鈕。 將 [組件版本] 和 [檔案版本] 值變更為 2.0.0.0。
開啟 ISampleInterface.vb 或 ISampleInterface.cs 檔。 將下列程式碼行加入至 ISampleInterface 介面。
Function GetDate() As Date
DateTime GetDate();
儲存檔案。
儲存專案。
以用滑鼠右鍵按一下 [TypeEquivalenceInterface] 專案,然後按一下 [建置]。 新版的類別庫 .dll 檔隨即進行編譯,並儲存至指定的建置輸出路徑 (例如,C:\TypeEquivalenceSample)。
修改執行階段類別
若要修改執行階段類別
在 Visual Studio 的 [檔案] 功能表上,指向 [開啟],再按一下 [專案/方案]。
在 [開啟專案] 對話方塊中,以滑鼠右鍵按一下 [TypeEquivalenceRuntime] 專案,然後按一下 [屬性]。 按一下 [應用程式] 索引標籤。 按一下 [組件資訊] 按鈕。 將 [組件版本] 和 [檔案版本] 值變更為 2.0.0.0。
開啟 SampleClass.vb 或 SampleClass.cs 檔。 將下列程式碼行加入至 SampleClass 類別。
Public Function GetDate() As DateTime Implements ISampleInterface.GetDate Return Now End Function
public DateTime GetDate() { return DateTime.Now; }
儲存檔案。
儲存專案。
以滑鼠右鍵按一下 [TypeEquivalenceRuntime] 專案,然後按一下 [建置]。 更新版的類別庫 .dll 檔隨即進行編譯,並儲存至先前指定的建置輸出路徑 (例如,C:\TypeEquivalenceSample)。
在 Windows 檔案總管中,開啟輸出路徑資料夾 (例如,C:\TypeEquivalenceSample)。 按兩下 [TypeEquivalenceClient.exe] 以執行程式。 這個程式沒有經過重新編譯,但是仍然反映出新版的 TypeEquivalenceRuntime 組件。