友元程序集 (C++)
适用的运行时,则 友元程序集 汇编语言功能在命名空间范围或全局范围内程序集中元素是可访问的一项或多项客户端程序集或的类型。 netmodules。
所有运行时
备注
(此语言功能不在所有运行时中支持。)
Windows 运行时
备注
(此语言功能在 Windows 运行时不支持。)
要求
编译器选项:/ZW
公共语言运行时
备注
使类型在命名空间范围或全局范围内程序集中元素可以访问客户端程序集或。netmodule
在元素中,指定程序集特性 InternalsVisibleToAttribute,并将客户端程序集的名称或。 将访问的 netmodule 键入在命名空间范围或全局范围在元素中。 您可以指定多个客户端程序集或。 netmodules 通过指定其他属性。
在客户端程序集或。 netmodule,使用 #using时,中,当引用组件程序集,通过 as_friend 属性。 如果您未指定 InternalsVisibleToAttribute的程序集指定 as_friend 属性,则将引发运行时异常,如果尝试访问一个类型在命名空间范围或全局范围在元素中。
会发生编译错误,如果包含 InternalsVisibleToAttribute 特性的程序集没有强名称,但是程序集使用 as_friend 属性的客户端。
虽然在命名空间范围和全局范围的类型可用于客户端程序集不知道或。 netmodule,成员可访问性仍然有效。 例如,您不能访问私有成员。
整访问键入程序集必须显式授予。 例如,C 无权访问的所有程序集输入程序集 A,如果程序集 C 引用程序集 B,和 B 可以访问所有的程序集输入程序集 A。
有关如何指定类型的可访问性的信息在程序集外,请参见 类型可见性"。
有关符号是使用 Visual 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();
}
Output
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");
}
};
下面的代码示例定义尝试访问私有类型元素不允许访问其私有类型的访问的客户一端。 由于运行时的行为,因此,如果要捕捉异常,必须尝试向私有类型 helper 函数的访问。
// 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");
}
}
Output
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();
}
Output
Class1::Test_Public