チュートリアル: マネージ アセンブリからの型の埋め込み (C# および Visual Basic)
厳密な名前のマネージ アセンブリから型情報を埋め込むと、アプリケーション内の型を疎結合にすることができるため、バージョンに依存しないアプリケーションを作成できます。 つまり、複数のバージョンのマネージ ライブラリの型を使用するようにプログラムを記述でき、バージョンごとに再コンパイルする必要がなくなります。
型の埋め込みは、Microsoft Office のオートメーション オブジェクトを使用するアプリケーションなど、COM 相互運用でよく使用されます。 型情報を埋め込むと、プログラムの同じビルドで、異なるコンピューター上にある異なるバージョンの Microsoft Office と連携できます。 また、型の埋め込みは完全なマネージ ソリューションでも使用できます。
型情報は、次の特性を持つアセンブリから埋め込むことができます。
アセンブリで、少なくとも 1 つのパブリック インターフェイスが公開されている。
埋め込みインターフェイスに、ComImport 属性と Guid 属性 (および一意の GUID) で注釈が付けられている。
アセンブリに、ImportedFromTypeLib 属性または PrimaryInteropAssembly 属性と、アセンブリ レベルの Guid 属性で注釈が付けられている (既定では、Visual Basic および Visual C# のプロジェクト テンプレートには、アセンブリ レベルの Guid 属性が含まれています)。
埋め込むことができるパブリック インターフェイスを指定したら、そのインターフェイスを実装するランタイム クラスを作成できます。 その後、クライアント プログラムでデザイン時にパブリック インターフェイスの型情報を埋め込むことができます。これは、パブリック インターフェイスを含むアセンブリを参照し、その参照の Embed Interop Types プロパティを True に設定することで行います。 この操作は、コマンド ライン コンパイラを使用し、/link コンパイラ オプションを使用してアセンブリを参照することと同じです。 クライアント プログラムでは、パブリック インターフェイスとして型指定されたランタイム オブジェクトのインスタンスを読み込むことができます。 新しいバージョンの厳密な名前のランタイム アセンブリを作成する場合でも、更新したランタイム アセンブリを使用してクライアント プログラムを再コンパイルする必要はありません。 クライアント プログラムでは、パブリック インターフェイスの埋め込み型情報に基づいて、利用可能なバージョンのランタイム アセンブリが引き続き使用されます。
型の埋め込みの主要な機能は COM 相互運用機能アセンブリからの型情報の埋め込みをサポートすることなので、完全なマネージ ソリューションで型情報を埋め込むときは、次の制限が適用されます。
COM 相互運用機能に固有の属性のみが埋め込まれます。他の属性は無視されます。
型がジェネリック パラメーターを使用し、ジェネリック パラメーターの型が埋め込み型である場合は、アセンブリの境界を越えてその型を使用することはできません。 アセンブリ境界を越える例としては、別のアセンブリからのメソッドの呼び出しや、別のアセンブリで定義されている型からの型の派生などがあります。
定数は埋め込まれません。
Dictionary クラスは、キーとしての埋め込み型をサポートしません。 独自のディクショナリ型を実装することで、キーとしての埋め込み型をサポートできます。
このチュートリアルでは、次の操作を実行します。
埋め込み可能な型情報を含んだパブリック インターフェイスを持つ厳密な名前のアセンブリを作成します。
パブリック インターフェイスを実装する厳密な名前のランタイム アセンブリを作成します。
パブリック インターフェイスの型情報を埋め込むクライアント プログラムを作成し、ランタイム アセンブリのクラスのインスタンスを作成します。
ランタイム アセンブリを変更し、再度ビルドします。
クライアント プログラムを実行し、クライアント プログラムを再コンパイルしなくても新しいバージョンのランタイム アセンブリが使用されていることを確認します。
注意
次の手順で参照している Visual Studio ユーザー インターフェイス要素の一部は、お使いのコンピューターでは名前や場所が異なる場合があります。これらの要素は、使用している Visual Studio のエディションや独自の設定によって決まります。詳細については、「Visual Studio での開発設定のカスタマイズ」を参照してください。
インターフェイスの作成
型の同値性のインターフェイス プロジェクトを作成するには
Visual Studio で、[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
[新しいプロジェクト] ダイアログ ボックスの [プロジェクトの種類] ペインで、[Windows] が選択されていることを確認します。 [テンプレート] ペインで [クラス ライブラリ] をクリックします。 [名前] ボックスに「TypeEquivalenceInterface」と入力し、[OK] をクリックします。 新しいプロジェクトが作成されます。
ソリューション エクスプローラーで、Class1.vb ファイルまたは Class1.cs ファイルを右クリックし、[名前の変更] をクリックします。 ファイルの名前を「ISampleInterface.vb」または「ISampleInterface.cs」に変更し、Enter キーを押します。 ファイルの名前を変更すると、クラスの名前も ISampleInterface に変更されます。 このクラスは、クラスのパブリック インターフェイスを表します。
TypeEquivalenceInterface プロジェクトを右クリックし、[プロパティ] をクリックします。 Visual Basic の [コンパイル] タブ、または Visual C# の [ビルド] タブをクリックします。 出力パスを、開発コンピューター上の有効な場所 (「C:\TypeEquivalenceSample」など) に設定します。 この場所は、このチュートリアルの後の手順でも使用します。
プロジェクト プロパティの編集を継続したまま、[署名] タブをクリックします。 [アセンブリの署名] オプションを選択します。 [厳密な名前のキー ファイルを選択してください] ボックスの一覧の [<新規作成...>] をクリックします。 [キー ファイル] ボックスに「key.snk」と入力します。 [キーファイルをパスワードで保護する] チェック ボックスをオフにします。 [OK] をクリックします。
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# を使用している場合は [Properties] フォルダーを展開します。 AssemblyInfo.vb ファイルまたは AssemblyInfo.cs ファイルをダブルクリックします。 次の属性をファイルに追加します。
<Assembly: ImportedFromTypeLib("")>
[assembly: ImportedFromTypeLib("")]
ファイルを保存します。
プロジェクトを保存します。
TypeEquivalenceInterface プロジェクトを右クリックし、[ビルド] をクリックします。 クラス ライブラリ .dll ファイルがコンパイルされ、指定したビルド出力パス (C:\TypeEquivalenceSample など) に保存されます。
ランタイム クラスの作成
型の同値性のランタイム プロジェクトを作成するには
Visual Studio で、[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
[新しいプロジェクト] ダイアログ ボックスの [プロジェクトの種類] ペインで、[Windows] が選択されていることを確認します。 [テンプレート] ペインで [クラス ライブラリ] をクリックします。 [名前] ボックスに「TypeEquivalenceRuntime」と入力し、[OK] をクリックします。 新しいプロジェクトが作成されます。
ソリューション エクスプローラーで、Class1.vb ファイルまたは Class1.cs ファイルを右クリックし、[名前の変更] をクリックします。 ファイルの名前を「SampleClass.vb」または「SampleClass.cs」に変更し、Enter キーを押します。 ファイルの名前を変更すると、クラスの名前も SampleClass に変更されます。 このクラスは、ISampleInterface インターフェイスを実装します。
TypeEquivalenceRuntime プロジェクトを右クリックし、[プロパティ] をクリックします。 Visual Basic の [コンパイル] タブ、または Visual C# の [ビルド] タブをクリックします。 出力パスを、TypeEquivalenceInterface プロジェクトで使用したものと同じ場所 (「C:\TypeEquivalenceSample」など) に設定します。
プロジェクト プロパティの編集を継続したまま、[署名] タブをクリックします。 [アセンブリの署名] オプションを選択します。 [厳密な名前のキー ファイルを選択してください] ボックスの一覧の [<新規作成...>] をクリックします。 [キー ファイル] ボックスに「key.snk」と入力します。 [キーファイルをパスワードで保護する] チェック ボックスをオフにします。 [OK] をクリックします。
TypeEquivalenceRuntime プロジェクトを右クリックし、[参照の追加] をクリックします。 [参照] タブをクリックし、出力パスのフォルダーに移動します。 TypeEquivalenceInterface.dll ファイルを選択し、[OK] をクリックします。
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」と入力し、[OK] をクリックします。 新しいプロジェクトが作成されます。
TypeEquivalenceClient プロジェクトを右クリックし、[プロパティ] をクリックします。 Visual Basic の [コンパイル] タブ、または Visual C# の [ビルド] タブをクリックします。 出力パスを、TypeEquivalenceInterface プロジェクトで使用したものと同じ場所 (「C:\TypeEquivalenceSample」など) に設定します。
TypeEquivalenceClient プロジェクトを右クリックし、[参照の追加] をクリックします。 [参照] タブをクリックし、出力パスのフォルダーに移動します。 TypeEquivalenceInterface.dll ファイルを選択し (TypeEquivalenceRuntime.dll ではありません)、[OK] をクリックします。
Visual Basic で、[プロジェクト] メニューの [すべてのファイルを表示] をクリックします。 Visual C# を使用している場合は、この手順を省略してください。
ソリューション エクスプローラーで、[参照設定] フォルダーを展開します。 TypeEquivalenceInterface への参照を選択します。 TypeEquivalenceInterface 参照の [プロパティ] ウィンドウで、"相互運用型の埋め込み" プロパティを 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 など) に保存されます。
ファイル エクスプローラーで、出力パスのフォルダーを開きます (たとえば、C: \TypeEquivalenceSample)。 TypeEquivalenceClient.exe をダブルクリックして、プログラムを実行します。 プログラムを再コンパイルしなくても、新しいバージョンの TypeEquivalenceRuntime アセンブリがプログラムに反映されます。