チュートリアル: Visual Studio でマネージド アセンブリからの型を埋め込む
厳密な名前を持つマネージド アセンブリから型情報を埋め込むと、アプリケーション内で型を疎結合して、バージョンに依存しないプログラムを実現できます。 つまり、任意のバージョンのマネージド ライブラリの型を使用してプログラムを記述でき、新しいバージョンごとに再コンパイルする必要はありません。
型の埋め込みは、COM 相互運用と共によく使用されます (Microsoft Office からのオートメーション オブジェクトを使用するアプリケーションなど)。 型情報を埋め込むと、同じビルドのプログラムを、別のコンピューター上にある別バージョンの Microsoft Office と連携させることができます。 ただし、フル マネージド ソリューションで型の埋め込みを使用することもできます。
埋め込み可能なパブリック インターフェイスを指定した後、それらのインターフェイスを実装するランタイム クラスを作成します。 クライアント プログラムでは、パブリック インターフェイスが含まれるアセンブリを参照し、参照の Embed Interop Types
プロパティを True
に設定することで、設計時にインターフェイスの型情報を埋め込むことができます。 クライアント プログラムでは、その後、それらのインターフェイスとして型指定されたランタイム オブジェクトのインスタンスを読み込むことができます。 これは、コマンド ライン コンパイラを使用し、EmbedInteropTypes コンパイラ オプションを使用してアセンブリを参照することに相当します。
厳密な名前を持つランタイム アセンブリの新バージョンを作成した場合でも、クライアント プログラムを再コンパイルする必要はありません。 クライアント プログラムでは、パブリック インターフェイスの埋め込まれた型情報を使用して、利用可能などのバージョンでも引き続き使用できます。
このチュートリアルでは、次の作業を行います。
- 埋め込み可能な型情報が含まれるパブリック インターフェイスを使用して、厳密な名前を持つアセンブリを作成する。
- そのパブリック インターフェイスを実装する、厳密な名前のランタイム アセンブリを作成する。
- パブリック インターフェイスから型情報を埋め込み、ランタイム アセンブリからクラスのインスタンスを作成する、クライアント プログラムを作成する。
- ランタイム アセンブリを変更し、リビルドする。
- クライアント プログラムを実行し、クライアント プログラムを再コンパイルしなくても、新バージョンのランタイム アセンブリが使用されることを確認する。
注意
次の手順で参照している Visual Studio ユーザー インターフェイス要素の一部は、お使いのコンピューターでは名前や場所が異なる場合があります。 これらの要素は、使用している Visual Studio のエディションや独自の設定によって決まります。 詳細については、「IDE をカスタマイズする」をご覧ください。
条件と制限
次の条件が満たされていると、アセンブリから型情報を埋め込むことができます。
- アセンブリが、少なくとも 1 つのパブリック インターフェイスを公開している。
- 埋め込みインターフェイスに、
ComImport
属性および一意の GUID のGuid
属性で注釈が付けられている。 - アセンブリに、
ImportedFromTypeLib
属性またはPrimaryInteropAssembly
属性、およびアセンブリ レベルのGuid
属性が付けられている。 既定では、Visual C# と Visual Basic のプロジェクト テンプレートには、アセンブリ レベルのGuid
属性が含まれています。
型の埋め込みの主な機能は、COM 相互運用アセンブリをサポートすることなので、フル マネージドのソリューションに型情報を埋め込む場合は、次の制限が適用されます。
- COM 相互運用に固有の属性のみが埋め込まれます。 他の属性は無視されます。
- 型でジェネリック パラメーターが使用されていて、ジェネリック パラメーターの型が埋め込まれる型である場合、その型をアセンブリの境界を越えて使用することはできません。 アセンブリの境界を越える場合の例としては、別のアセンブリからメソッドを呼び出す場合や、別のアセンブリで定義されている型から型を派生させる場合です。
- 定数は埋め込まれません。
- System.Collections.Generic.Dictionary<TKey,TValue> クラスでは、埋め込み型をキーとして利用できません。 埋め込み型をキーとしてサポートするために、独自のディクショナリ型を実装することは可能です。
インターフェイスの作成
最初のステップは、型等価性インターフェイス プロジェクトを作成することです。
Visual Studio で、[ファイル][新規][プロジェクト] の順に選択します。
[新しいプロジェクトの作成] ダイアログ ボックスで、 [Search for templates](テンプレートの検索) ボックスに「クラス ライブラリ」と入力します。 一覧から C# または Visual Basic のクラス ライブラリ (.NET Framework) テンプレートを選択し、 [次へ] を選択します。
[新しいプロジェクトの構成] ダイアログ ボックスの [プロジェクト名] に「TypeEquivalenceInterface」と入力し、 [作成] を選択します。 新しいプロジェクトが作成されます。
ソリューション エクスプローラーで、Class1.cs ファイルまたは Class1.vb ファイルを右クリックし、 [名前の変更] を選択して、ファイル名を Class1 から ISampleInterface に変更します。 クラスの名前も
ISampleInterface
変更するかどうかを確認を求めるメッセージが表示されたら、[はい] と応答します。 このクラスは、クラスのパブリック インターフェイスを表します。ソリューション エクスプローラーで TypeEquivalenceInterface プロジェクトを右クリックし、 [プロパティ] を選択します。
[プロパティ] 画面の左側のウィンドウで [ビルド] を選択し、 [出力パス] をお使いのコンピューター上の場所 (C:\TypeEquivalenceSample など) に設定します。 このチュートリアル全体で同じ場所を使用します。
[プロパティ] 画面の左側のペインで [ビルド]>[Strong naming] (厳密な名前付け) を選んで、[アセンブリに署名する] チェック ボックスをオンにします。 [厳密な名前のキー ファイル] で、[参照] を選びます。
TypeEquivalenceInterface プロジェクトで作成した key.snk ファイルに移動して選んでから、[OK] を選びます。 詳しくは、公開キーと秘密キーのペアの作成に関する記事をご覧ください。
コード エディターで ISampleInterface クラス ファイルを開き、その内容を次のコードに置き換えて、
ISampleInterface
インターフェイスを作成します。using System; using System.Runtime.InteropServices; namespace TypeEquivalenceInterface { [ComImport] [Guid("8DA56996-A151-4136-B474-32784559F6DF")] public interface ISampleInterface { void GetUserInput(); string UserInput { get; } } }
Imports System.Runtime.InteropServices <ComImport()> <Guid("8DA56996-A151-4136-B474-32784559F6DF")> Public Interface ISampleInterface Sub GetUserInput() ReadOnly Property UserInput As String End Interface
[ツール] メニューの [GUID の作成] を選択し、 [GUID の作成] ダイアログ ボックスで [レジストリ形式] を選択します。 [コピー] を選択し、 [終了] を選択します。
コードの
Guid
属性で、サンプルの GUID をコピーした GUID に置き換えて、中かっこ ({ }) を削除します。ソリューション エクスプローラーで [プロパティ] フォルダーを展開し、AssemblyInfo.cs または AssemblyInfo.vb ファイルを選択します。 コード エディターで、次の属性をファイルに追加します。
[assembly: ImportedFromTypeLib("")]
<Assembly: ImportedFromTypeLib("")>
[ファイル]>[すべて保存] を選択するか、Ctrl+Shift+S キーを押して、ファイルとプロジェクトを保存します。
ソリューション エクスプローラーで TypeEquivalenceInterface プロジェクトを右クリックし、 [ビルド] を選択します。 クラス ライブラリの DLL ファイルがコンパイルされ、指定したビルド出力パス (たとえば、C:\TypeEquivalenceSample) に保存されます。
ランタイム クラスを作成する
次に、型等価性ランタイム クラスを作成します。
Visual Studio で、[ファイル][新規][プロジェクト] の順に選択します。
[新しいプロジェクトの作成] ダイアログ ボックスで、 [Search for templates](テンプレートの検索) ボックスに「クラス ライブラリ」と入力します。 一覧から C# または Visual Basic のクラス ライブラリ (.NET Framework) テンプレートを選択し、 [次へ] を選択します。
[新しいプロジェクトの構成] ダイアログ ボックスの [プロジェクト名] に「TypeEquivalenceRuntime」と入力し、 [作成] を選択します。 新しいプロジェクトが作成されます。
ソリューション エクスプローラーで、Class1.cs ファイルまたは Class1.vb ファイルを右クリックし、 [名前の変更] を選択して、ファイル名を Class1 から SampleClass に変更します。 クラスの名前も
SampleClass
変更するかどうかを確認を求めるメッセージが表示されたら、[はい] と応答します。 このクラスは、ISampleInterface
インターフェイスを実装します。ソリューション エクスプローラーで TypeEquivalenceInterface プロジェクトを右クリックし、 [プロパティ] を選択します。
[プロパティ] 画面の左側のペインで [ビルド] を選び、[出力パス] を TypeEquivalenceInterface プロジェクトで使用したのと同じ場所 (たとえば、C:\TypeEquivalenceSample) に設定します。
[プロパティ] 画面の左側のペインで [ビルド]>[Strong naming] (厳密な名前付け) を選んで、[アセンブリに署名する] チェック ボックスをオンにします。 [厳密な名前のキー ファイル] で、[参照] を選びます。
TypeEquivalenceInterface プロジェクトで作成した key.snk ファイルに移動して選んでから、[OK] を選びます。 詳しくは、公開キーと秘密キーのペアの作成に関する記事をご覧ください。
ソリューション エクスプローラーで、TypeEquivalenceRuntime プロジェクトを右クリックし、[追加]>[参照] を選択します。
[参照マネージャー] ダイアログ ボックスで [参照] を選択し、出力パスのフォルダーを参照します。 TypeEquivalenceInterface.dll ファイルを選択し、 [追加] を選択して、 [OK] を選択します。
ソリューション エクスプローラーで [参照] フォルダーを展開し、TypeEquivalenceInterface 参照を選択します。 [プロパティ] ウィンドウで、まだ設定されていない場合は [特定バージョン] を [False] に設定します。
コード エディターで SampleClass クラス ファイルを開き、その内容を次のコードに置き換えて、
SampleClass
クラスを作成します。using System; 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(); } } }
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
[ファイル]>[すべて保存] を選択するか、Ctrl+Shift+S キーを押して、ファイルとプロジェクトを保存します。
ソリューション エクスプローラーで TypeEquivalenceRuntime プロジェクトを右クリックし、 [ビルド] を選択します。 クラス ライブラリの DLL ファイルがコンパイルされ、指定したビルド出力パスに保存されます。
クライアント プロジェクトを作成する
最後に、インターフェイス アセンブリを参照する型等価性クライアント プログラムを作成します。
Visual Studio で、[ファイル][新規][プロジェクト] の順に選択します。
[新しいプロジェクトの作成] ダイアログ ボックスで、 [Search for templates](テンプレートの検索) ボックスに「コンソール」と入力します。 一覧から C# または Visual Basic のコンソール アプリ (.NET Framework) テンプレートを選択し、 [次へ] を選択します。
[新しいプロジェクトの構成] ダイアログ ボックスの [プロジェクト名] に「TypeEquivalenceClient」と入力し、 [作成] を選択します。 新しいプロジェクトが作成されます。
ソリューション エクスプローラーで TypeEquivalenceClient プロジェクトを右クリックし、 [プロパティ] を選択します。
[プロパティ] 画面の左側のウィンドウで [ビルド] を選択し、 [出力パス] を TypeEquivalenceInterface プロジェクトで使用したのと同じ場所 (たとえば、C:\TypeEquivalenceSample) に設定します。
ソリューション エクスプローラーで TypeEquivalenceClient プロジェクトを右クリックし、[追加]>[参照] を選択します。
[参照マネージャー] ダイアログで、TypeEquivalenceInterface.dll ファイルが一覧に既に表示されている場合は、それを選択します。 表示されていない場合は、 [参照] を選択し、出力パス フォルダーを参照して、(TypeEquivalenceRuntime.dll ではなく) TypeEquivalenceInterface.dll ファイルを選択し、 [追加] を選択します。 [OK] を選択します。
ソリューション エクスプローラーで [参照] フォルダーを展開し、TypeEquivalenceInterface 参照を選択します。 [プロパティ] ウィンドウで、 [相互運用型の埋め込み] を [True] に設定します。
コード エディターで Program.cs または Module1.vb ファイルを開き、その内容を次のコードに置き換えて、クライアント プログラムを作成します。
using System; using System.Reflection; using TypeEquivalenceInterface; 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(); } } }
Imports System.Reflection Imports TypeEquivalenceInterface 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
[ファイル]>[すべて保存] を選択するか、Ctrl+Shift+S キーを押して、ファイルとプロジェクトを保存します。
Ctrl+F5 キーを押し、プログラムをビルドして実行します。 コンソールの出力にアセンブリのバージョン 1.0.0.0 が返されることに注意してください。
インターフェイスを変更する
ここでは、インターフェイス アセンブリを変更して、そのバージョンを変更します。
Visual Studio で、[ファイル]>[開く]>[プロジェクト/ソリューション] を選択し、TypeEquivalenceInterface プロジェクトを開きます。
ソリューション エクスプローラーで TypeEquivalenceInterface プロジェクトを右クリックし、 [プロパティ] を選択します。
[プロパティ] 画面の左側のウィンドウで [アプリケーション] を選択し、 [アセンブリ情報] を選択します。
[アセンブリ情報] ダイアログ ボックスで、 [アセンブリのバージョン] と [ファイルのバージョン] の値を「2.0.0.0」に変更して、 [OK] を選択します。
SampleInterface.cs ファイルまたは SampleInterface.vb ファイルを開き、次のコード行を
ISampleInterface
インターフェイスに追加します。DateTime GetDate();
Function GetDate() As Date
[ファイル]>[すべて保存] を選択するか、Ctrl+Shift+S キーを押して、ファイルとプロジェクトを保存します。
ソリューション エクスプローラーで TypeEquivalenceInterface プロジェクトを右クリックし、 [ビルド] を選択します。 クラス ライブラリの DLL ファイルの新しいバージョンがコンパイルされて、ビルド出力パスに保存されます。
ランタイム クラスを変更する
また、ランタイム クラスを変更し、そのバージョンを更新します。
Visual Studio で、[ファイル]>[開く]>[プロジェクト/ソリューション] を選択し、TypeEquivalenceRuntime プロジェクトを開きます。
ソリューション エクスプローラーで TypeEquivalenceRuntime プロジェクトを右クリックし、 [プロパティ] を選択します。
[プロパティ] 画面の左側のウィンドウで [アプリケーション] を選択し、 [アセンブリ情報] を選択します。
[アセンブリ情報] ダイアログ ボックスで、 [アセンブリのバージョン] と [ファイルのバージョン] の値を「2.0.0.0」に変更して、 [OK] を選択します。
SampleClass.cs ファイルまたは SampleClass.vb ファイルを開き、次のコードを
SampleClass
クラスに追加します。public DateTime GetDate() { return DateTime.Now; }
Public Function GetDate() As DateTime Implements ISampleInterface.GetDate Return Now End Function
[ファイル]>[すべて保存] を選択するか、Ctrl+Shift+S キーを押して、ファイルとプロジェクトを保存します。
ソリューション エクスプローラーで TypeEquivalenceRuntime プロジェクトを右クリックし、 [ビルド] を選択します。 クラス ライブラリの DLL ファイルの新しいバージョンがコンパイルされて、ビルド出力パスに保存されます。
更新されたクライアント プログラムを実行する
ビルド出力フォルダーの場所に移動し、TypeEquivalenceClient.exe を実行します。 プログラムを再コンパイルしなくても、コンソール出力に TypeEquivalenceRuntime
アセンブリの新しいバージョン 2.0.0.0 が反映されていることに注意してください。
関連項目
.NET