逐步解說:從 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 特有的屬性會內嵌,其他屬性會遭忽略。

  • 如果有某個型別使用泛型參數,而該泛型參數的型別為內嵌的型別,則該型別無法超出組件範圍來使用。 超出組件範圍使用的例子,包括呼叫來自其他組件中的方法,或從其他組件中所定義的型別衍生另一個型別。

  • 常數不會內嵌。

  • System.Collections.Generic.Dictionary<TKey, TValue> 類別不支援以內嵌的型別做為索引鍵。 您可以實作您自己的字典型別,以支援以內嵌的型別做為索引鍵。

在這個逐步解說中,您將執行下列工作:

  • 建立具有公用介面的強式名稱組件,這個介面內含可內嵌的型別資訊。

  • 建立實作公用介面的強式名稱執行階段組件。

  • 建立內嵌公用介面之型別資訊的用戶端程式,並從執行階段組件建立類別的執行個體。

  • 修改並重新建置執行階段組件。

  • 執行用戶端程式以查看是否正在使用新版的執行階段組件,而不必重新編譯用戶端程式。

注意事項注意事項

您的電腦可能會在下列說明中,以不同名稱或位置顯示某些 Visual Studio 使用者介面項目。 您所擁有的 Visual Studio 版本以及使用的設定會決定這些項目。 如需詳細資訊,請參閱 Visual Studio 設定

建立介面

若要建立型別等價介面專案

  1. 在 Visual Studio 中的 [檔案] 功能表上,指向 [新增] 然後按一下 [專案]。

  2. 在 [新增專案] 對話方塊的 [專案類型] 窗格中,確定已選取 [Windows]。 選取 [範本] 窗格中的 [類別庫]。 在 [名稱] 方塊中輸入 TypeEquivalenceInterface,然後按一下 [確定]。 接著會建立新專案。

  3. 在 [方案總管] 中,以滑鼠右鍵按一下 Class1.vb 或 Class1.cs 檔,然後按一下 [重新命名]。 將檔案重新命名為 ISampleInterface.vb 或 ISampleInterface.cs,並按下 ENTER。 重新命名檔案時也會將類別重新命名為 ISampleInterface。 這個類別將會代表類別的公用介面。

  4. 以滑鼠右鍵按一下 [TypeEquivalenceInterface] 專案,然後按一下 [屬性]。 在 Visual Basic 中按一下 [編譯] 索引標籤,在 Visual C# 中則按一下 [建置] 索引標籤。 將輸出路徑設定為開發電腦上的有效位置,例如 C:\TypeEquivalenceSample。 在本逐步解說的稍後步驟中也會用到這個位置。

  5. 當您還在編輯專案屬性時,按一下 [簽署] 索引標籤。 選取 [簽署組件] 選項。 在 [選擇強式名稱金鑰檔] 清單中,按一下 [<新增>]。 在 [金鑰檔名稱] 方塊中,輸入 key.snk。 清除 [以密碼保護我的金鑰檔] 核取方塊。 按一下 [確定]。

  6. 開啟 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; }
    
    
    ...
    
    
        }
    }
    
  7. 在 [工具] 功能表上按一下 [建立 GUID]。 在 [建立 GUID] 對話方塊中,按一下 [登錄格式],再按一下 [複製]。 按一下 [結束]。

  8. 在 Guid 屬性中刪除範例 GUID,並貼上您從 [建立 GUID] 對話方塊複製的 GUID。 從複製的 GUID 移除大括號 ({})。

  9. 在 Visual Basic 中,按一下 [專案] 功能表上的 [顯示所有檔案]。 如果您使用 Visual C#,請跳過這個步驟。

  10. 如果您是使用 Visual Basic,請在 [方案總管] 中展開 [我的專案] 資料夾。 如果是使用 Visual C#,則展開 [屬性] 資料夾。 按兩下[ AssemblyInfo.vb] 或 [AssemblyInfo.cs] 檔, 將下列屬性加入至檔案。

    <Assembly: ImportedFromTypeLib("")> 
    
    [assembly: ImportedFromTypeLib("")]
    

    儲存檔案。

  11. 儲存專案。

  12. 以用滑鼠右鍵按一下 [TypeEquivalenceInterface] 專案,然後按一下 [建置]。 類別庫 .dll 檔隨即進行編譯,並儲存至指定的建置輸出路徑 (例如,C:\TypeEquivalenceSample)。

建立執行階段類別

若要建立型別等價執行階段專案

  1. 在 Visual Studio 中的 [檔案] 功能表上,指向 [新增] 然後按一下 [專案]。

  2. 在 [新增專案] 對話方塊的 [專案類型] 窗格中,確定已選取 [Windows]。 選取 [範本] 窗格中的 [類別庫]。 在 [名稱] 方塊中輸入 TypeEquivalenceRuntime,然後按一下 [確定]。 接著會建立新專案。

  3. 在 [方案總管] 中,以滑鼠右鍵按一下 Class1.vb 或 Class1.cs 檔,然後按一下 [重新命名]。 將檔案重新命名為 SampleClass.vb 或 SampleClass.cs,並按下 ENTER。 重新命名檔案時也會將類別重新命名為 SampleClass。 這個類別會實作 ISampleInterface 介面。

  4. 以滑鼠右鍵按一下 [TypeEquivalenceRuntime] 專案,然後按一下 [屬性]。 在 Visual Basic 中按一下 [編譯] 索引標籤,在 Visual C# 中則按一下 [建置] 索引標籤。 將輸出路徑設定為您在 TypeEquivalenceInterface 專案中使用的同樣位置,例如 C:\TypeEquivalenceSample。

  5. 當您還在編輯專案屬性時,按一下 [簽署] 索引標籤。 選取 [簽署組件] 選項。 在 [選擇強式名稱金鑰檔] 清單中,按一下 [<新增>]。 在 [金鑰檔名稱] 方塊中,輸入 key.snk。 清除 [以密碼保護我的金鑰檔] 核取方塊。 按一下 [確定]。

  6. 以滑鼠右鍵按一下 [TypeEquivalenceRuntime] 專案,然後按一下 [加入參考]。 按一下 [瀏覽] 索引標籤,然後瀏覽至輸出路徑資料夾。 選取 [TypeEquivalenceInterface.dll] 檔案,然後按一下 [確定]。

  7. 在 Visual Basic 中,按一下 [專案] 功能表上的 [顯示所有檔案]。 如果您使用 Visual C#,請跳過這個步驟。

  8. 在 [方案總管] 中,展開 [參考] 資料夾。 選取 [TypeEquivalenceInterface] 參考。 在 [TypeEquivalenceInterface] 參考的 [屬性] 視窗中,將 [特定版本] 屬性設定為 [False]。

  9. 將下列程式碼加入至 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();
            }
    
    
    ...
    
    
        }
    }
    
  10. 儲存專案。

  11. 以滑鼠右鍵按一下 [TypeEquivalenceRuntime] 專案,然後按一下 [建置]。 類別庫 .dll 檔隨即進行編譯,並儲存至指定的建置輸出路徑 (例如,C:\TypeEquivalenceSample)。

建立用戶端專案

若要建立型別等價用戶端專案

  1. 在 Visual Studio 中的 [檔案] 功能表上,指向 [新增] 然後按一下 [專案]。

  2. 在 [新增專案] 對話方塊的 [專案類型] 窗格中,確定已選取 [Windows]。 選取 [主控台應用程式] 中的 [範本] 窗格。 在 [名稱] 方塊中輸入 TypeEquivalenceClient,然後按一下 [確定]。 接著會建立新專案。

  3. 以滑鼠右鍵按一下 [TypeEquivalenceClient] 專案,然後按一下 [屬性]。 在 Visual Basic 中按一下 [編譯] 索引標籤,在 Visual C# 中則按一下 [建置] 索引標籤。 將輸出路徑設定為您在 TypeEquivalenceInterface 專案中使用的同樣位置,例如 C:\TypeEquivalenceSample。

  4. 以滑鼠右鍵按一下 [TypeEquivalenceClient] 專案,然後按一下 [加入參考]。 按一下 [瀏覽] 索引標籤,然後瀏覽至輸出路徑資料夾。 選取 [TypeEquivalenceInterface.dll] (而非 [TypeEquivalenceRuntime.dll]) 檔案,然後按一下 [確定]。

  5. 在 Visual Basic 中,按一下 [專案] 功能表上的 [顯示所有檔案]。 如果您使用 Visual C#,請跳過這個步驟。

  6. 在 [方案總管] 中,展開 [參考] 資料夾。 選取 [TypeEquivalenceInterface] 參考。 在 [TypeEquivalenceInterface] 參考的 [屬性] 視窗中,將 [內嵌 Interop 型別] 屬性設定為 [True]。

  7. 將下列程式碼加入至 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();
            }
        }
    }
    
  8. 按 CTRL+F5 建置和執行程式。

修改介面

若要修改介面

  1. 在 Visual Studio 的 [檔案] 功能表上,指向 [開啟],再按一下 [專案/方案]。

  2. 在 [開啟專案] 對話方塊中,以滑鼠右鍵按一下 [TypeEquivalenceInterface] 專案,然後按一下 [屬性]。 按一下 [應用程式] 索引標籤。 按一下 [組件資訊] 按鈕。 將 [組件版本] 和 [檔案版本] 值變更為 2.0.0.0。

  3. 開啟 ISampleInterface.vb 或 ISampleInterface.cs 檔。 將下列程式碼行加入至 ISampleInterface 介面。

    Function GetDate() As Date
    
    DateTime GetDate();
    

    儲存檔案。

  4. 儲存專案。

  5. 以用滑鼠右鍵按一下 [TypeEquivalenceInterface] 專案,然後按一下 [建置]。 新版的類別庫 .dll 檔隨即進行編譯,並儲存至指定的建置輸出路徑 (例如,C:\TypeEquivalenceSample)。

修改執行階段類別

若要修改執行階段類別

  1. 在 Visual Studio 的 [檔案] 功能表上,指向 [開啟],再按一下 [專案/方案]。

  2. 在 [開啟專案] 對話方塊中,以滑鼠右鍵按一下 [TypeEquivalenceRuntime] 專案,然後按一下 [屬性]。 按一下 [應用程式] 索引標籤。 按一下 [組件資訊] 按鈕。 將 [組件版本] 和 [檔案版本] 值變更為 2.0.0.0。

  3. 開啟 SampleClass.vb 或 SampleClass.cs 檔。 將下列程式碼行加入至 SampleClass 類別。

    Public Function GetDate() As DateTime Implements ISampleInterface.GetDate
        Return Now
    End Function
    
    public DateTime GetDate()
    {
        return DateTime.Now;
    }
    

    儲存檔案。

  4. 儲存專案。

  5. 以滑鼠右鍵按一下 [TypeEquivalenceRuntime] 專案,然後按一下 [建置]。 更新版的類別庫 .dll 檔隨即進行編譯,並儲存至先前指定的建置輸出路徑 (例如,C:\TypeEquivalenceSample)。

  6. 在 Windows 檔案總管中,開啟輸出路徑資料夾 (例如,C:\TypeEquivalenceSample)。 按兩下 [TypeEquivalenceClient.exe] 以執行程式。 這個程式沒有經過重新編譯,但是仍然反映出新版的 TypeEquivalenceRuntime 組件。

請參閱

參考

/link (Visual Basic)

/link (C# 編譯器選項)

概念

C# 程式設計手冊

其他資源

Visual Basic 程式設計手冊

使用組件設計程式