フレンド アセンブリ (C++)

該当するランタイムの場合、"フレンド アセンブリ" 言語機能により、アセンブリ コンポーネントの名前空間スコープまたはグローバル スコープの型に、1 つ以上のクライアント アセンブリまたは .netmodule からアクセスできるようになります。

すべてのランタイム

注釈

(この言語機能は、どのランタイムでもサポートされていません。)

Windows ランタイム

注釈

(Windows ランタイムでは、この言語機能はサポートされていません。)

必要条件

コンパイラ オプション: /ZW

共通言語ランタイム

注釈

アセンブリ コンポーネントの名前空間スコープまたはグローバル スコープの型に、クライアント アセンブリまたは .netmodule からアクセスできるようにするには:

  1. コンポーネントで、アセンブリ属性 InternalsVisibleToAttribute を指定し、コンポーネント内の名前空間スコープまたはグローバル スコープの型にアクセスするクライアント アセンブリまたは .netmodule の名前を渡します。 複数のクライアント アセンブリまたは .netmodule を指定するには、追加の属性を指定します。

  2. クライアント アセンブリまたは .netmodule で #using を使ってコンポーネント アセンブリを参照する場合は、as_friend 属性を渡します。 InternalsVisibleToAttribute を指定しないアセンブリに対して as_friend 属性を指定する場合、コンポーネント内の名前空間スコープまたはグローバル スコープの型にアクセスしようとすると、実行時例外がスローされます。

InternalsVisibleToAttribute 属性を含むアセンブリに厳密な名前がなく、as_friend 属性を使うクライアント アセンブリにはある場合は、ビルド エラーが発生します。

名前空間スコープとグローバル スコープの型は、クライアント アセンブリまたは .netmodule に認識されますが、メンバーのアクセシビリティは引き続き有効です。 たとえば、プライベート メンバーにはアクセスできません。

アセンブリ内のすべての型へのアクセスは、明示的に許可する必要があります。 たとえば、アセンブリ C がアセンブリ B を参照し、アセンブリ B がアセンブリ A のすべての型にアクセスできる場合、アセンブリ C はアセンブリ A のすべての型にアクセスできるわけではありません。

Microsoft C++ コンパイラを使ってビルドされたアセンブリに署名する方法、つまり厳密な名前を付ける方法については、「厳密名アセンブリ (アセンブリ署名) (C++/CLI)」を参照してください。

フレンド アセンブリ機能を使う代わりに、StrongNameIdentityPermission を使って、個々の型へのアクセスを制限することができます。

必要条件

コンパイラ オプション: /clr

次のコード例では、コンポーネント内の型にアクセスできるクライアント アセンブリを指定するコンポーネントを定義しています。

// friend_assemblies.cpp
// compile by using: /clr /LD
using namespace System::Runtime::CompilerServices;
using namespace System;
// an assembly attribute, not bound to a type
[assembly:InternalsVisibleTo("friend_assemblies_2")];

ref class Class1 {
public:
   void Test_Public() {
      Console::WriteLine("Class1::Test_Public");
   }
};

次のコード例では、コンポーネント内のプライベート型にアクセスしています。

// friend_assemblies_2.cpp
// compile by using: /clr
#using "friend_assemblies.dll" as_friend

int main() {
   Class1 ^ a = gcnew Class1;
   a->Test_Public();
}
Class1::Test_Public

次のコード例では、コンポーネントを定義していますが、コンポーネント内の型にアクセスするクライアント アセンブリを指定していません。

コンポーネントが /opt:noref を使ってリンクされていることに注目してください。 これにより、コンポーネントのメタデータにプライベート型が出力されるようになります。これは、InternalsVisibleTo 属性が存在する場合は必要ありません。 詳細については、「/OPT (最適化)」を参照してください。

// friend_assemblies_3.cpp
// compile by using: /clr /LD /link /opt:noref
using namespace System;

ref class Class1 {
public:
   void Test_Public() {
      Console::WriteLine("Class1::Test_Public");
   }
};

次のコード例では、プライベート型へのアクセスを許可していないコンポーネント内のプライベート型にアクセスしようとするクライアントを定義しています。 ランタイムの動作を考慮すると、例外をキャッチする場合は、ヘルパー関数でプライベート型にアクセスを試みる必要があります。

// friend_assemblies_4.cpp
// compile by using: /clr
#using "friend_assemblies_3.dll" as_friend
using namespace System;

void Test() {
   Class1 ^ a = gcnew Class1;
}

int main() {
   // to catch this kind of exception, use a helper function
   try {
      Test();
   }
   catch(MethodAccessException ^ e) {
      Console::WriteLine("caught an exception");
   }
}
caught an exception

次のコード例は、コンポーネント内の型にアクセスできるクライアント アセンブリを指定した厳密な名前のコンポーネントを作成する方法を示しています。

// friend_assemblies_5.cpp
// compile by using: /clr /LD /link /keyfile:friend_assemblies.snk
using namespace System::Runtime::CompilerServices;
using namespace System;
// an assembly attribute, not bound to a type

[assembly:InternalsVisibleTo("friend_assemblies_6, PublicKey=00240000048000009400000006020000002400005253413100040000010001000bf45d77fd991f3bff0ef51af48a12d35699e04616f27ba561195a69ebd3449c345389dc9603d65be8cd1987bc7ea48bdda35ac7d57d3d82c666b7fc1a5b79836d139ef0ac8c4e715434211660f481612771a9f7059b9b742c3d8af00e01716ed4b872e6f1be0e94863eb5745224f0deaba5b137624d7049b6f2d87fba639fc5")];

private ref class Class1 {
public:
   void Test_Public() {
      Console::WriteLine("Class1::Test_Public");
   }
};

このコンポーネントでは、公開キーを指定する必要があることに注目してください。 コマンド プロンプトで次のコマンドを順番に実行して、キー ペアを作成し、公開キーを取得することをお勧めします。

sn -d friend_assemblies.snk

sn -k friend_assemblies.snk

sn -i friend_assemblies.snk friend_assemblies.snk

sn -pc friend_assemblies.snk key.publickey

sn -tp key.publickey

次のコード例では、厳密な名前のコンポーネント内のプライベート型にアクセスしています。

// friend_assemblies_6.cpp
// compile by using: /clr /link /keyfile:friend_assemblies.snk
#using "friend_assemblies_5.dll" as_friend

int main() {
   Class1 ^ a = gcnew Class1;
   a->Test_Public();
}
Class1::Test_Public

関連項目

ランタイム プラットフォームのコンポーネントの拡張機能