Friend 어셈블리(C++)
적용 가능한 런타임의 경우 friend 어셈블리 언어 기능은 하나 이상의 클라이언트 어셈블리 또는 .netmodules에 액세스할 수 있는 어셈블리 구성 요소의 네임스페이스 범위 또는 전역 범위에 있는 형식을 만듭니다.
모든 런타임
설명
(이 언어 기능은 모든 런타임에서 지원되지 않습니다.)
Windows Runtime
설명
Windows 런타임에서는 이 언어 기능이 지원되지 않습니다.
요구 사항
컴파일러 옵션: /ZW
공용 언어 런타임
설명
어셈블리 구성 요소의 네임스페이스 범위 또는 전역 범위에서 형식을 클라이언트 어셈블리 또는 .netmodule에 액세스할 수 있도록 하려면
구성 요소에서 어셈블리 특성을 InternalsVisibleToAttribute지정하고 구성 요소의 네임스페이스 범위 또는 전역 범위에서 형식에 액세스하는 클라이언트 어셈블리 또는 .netmodule의 이름을 전달합니다. 추가 특성을 지정하여 여러 클라이언트 어셈블리 또는 .netmodules를 지정할 수 있습니다.
클라이언트 어셈블리 또는 .netmodule에서 구성 요소 어셈블리를 참조
#using
할 때 특성을 전달as_friend
합니다. 지정하지 않는 어셈블리의 특성을 지정as_friend
InternalsVisibleToAttribute
하면 구성 요소의 네임스페이스 범위 또는 전역 범위에서 형식에 액세스하려고 하면 런타임 예외가 throw됩니다.
특성이 포함된 InternalsVisibleToAttribute 어셈블리에 강력한 이름이 없지만 특성을 사용하는 as_friend
클라이언트 어셈블리가 있는 경우 빌드 오류가 발생합니다.
네임스페이스 범위 및 전역 범위의 형식을 클라이언트 어셈블리 또는 .netmodule에 알 수 있지만 멤버 접근성은 여전히 적용됩니다. 예를 들어 프라이빗 멤버에 액세스할 수 없습니다.
어셈블리의 모든 형식에 대한 액세스 권한을 명시적으로 부여해야 합니다. 예를 들어 어셈블리 C가 어셈블리 B를 참조하고 어셈블리 B가 어셈블리 A의 모든 형식에 액세스할 수 있는 경우 어셈블리 C는 어셈블리 A의 모든 형식에 액세스할 수 없습니다.
Microsoft C++ 컴파일러를 사용하여 빌드된 어셈블리에 강력한 이름을 지정하는 방법, 즉 서명하는 방법에 대한 자세한 내용은 강력한 이름 어셈블리(어셈블리 서명)(C++/CLI)를 참조하세요.
friend 어셈블리 기능을 사용하는 대신 개별 형식에 대한 액세스를 제한하는 데 사용할 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");
}
};
다음 코드 예제에서는 프라이빗 형식에 대한 액세스 권한을 부여하지 않는 구성 요소의 프라이빗 형식에 액세스하려는 클라이언트를 정의합니다. 런타임의 동작으로 인해 예외를 catch하려는 경우 도우미 함수의 프라이빗 형식에 액세스하려고 시도해야 합니다.
// 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