Дружественные сборки (C++)
Для применимых сред выполнения функция языка дружественных сборок делает типы, которые находятся в области пространства имен или глобальной области в компоненте сборки, доступном для одной или нескольких клиентских сборок или .netmodules.
Все среды выполнения
Замечания
(Эта функция языка не поддерживается во всех средах выполнения.)
Среда выполнения Windows
Замечания
(В среде выполнения Windows эта возможность языка не поддерживается.)
Требования
Параметр компилятора: /ZW
Среда CLR
Замечания
Создание типов в области пространства имен или глобальной области в компоненте сборки, доступном для клиентской сборки или .netmodule.
В компоненте укажите атрибут InternalsVisibleToAttributeсборки и передайте имя клиентской сборки или .netmodule, которая будет получать доступ к типам в области пространства имен или глобальной области в компоненте. Можно указать несколько клиентских сборок или .netmodules, указав дополнительные атрибуты.
При ссылке на сборку
#using
компонента при использовании клиентской сборки или .netmodule передайтеas_friend
атрибут. Если указать атрибут для сборки, которая не указанаas_friend
InternalsVisibleToAttribute
, исключение среды выполнения будет возникать, если вы пытаетесь получить доступ к типу в области пространства имен или глобальной области в компоненте.
Ошибка сборки приведет к тому, что сборка, содержащая InternalsVisibleToAttribute атрибут, не имеет строгого имени, но клиентская сборка, использующая as_friend
атрибут.
Хотя типы в области пространства имен и глобальной области могут быть известны клиентской сборке или .netmodule, специальные возможности членов по-прежнему действуют. Например, вы не можете получить доступ к частному члену.
Доступ ко всем типам в сборке должен быть явно предоставлен. Например, сборка C не имеет доступа ко всем типам в сборке A, если сборка C ссылается на сборку B и сборку B имеет доступ ко всем типам в сборке 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