Assemblies amigáveis (C++)
Para runtimes aplicáveis, o recurso de linguagem assemblies amigáveis torna os tipos que estão no escopo do namespace ou no escopo global em um componente de assembly acessível a um ou mais assemblies de cliente ou a .netmodules.
Todos os Runtimes
Comentários
(Esse recurso de linguagem não é compatível com todos os runtimes.)
Windows Runtime
Comentários
(Esse recurso de linguagem não é compatível com o Windows Runtime.)
Requisitos
Opção do compilador: /ZW
Common Language Runtime
Comentários
Para tornar os tipos no escopo do namespace ou no escopo global em um componente de assembly acessível a um assembly de cliente ou ao .netmodule
No componente, especifique um atributo InternalsVisibleToAttribute de assembly e passe o nome do assembly do cliente ou .netmodule que acessará tipos no escopo do namespace ou no escopo global no componente. Você pode especificar vários assemblies de cliente ou .netmodules especificando atributos adicionais.
No assembly do cliente ou .netmodule, quando você fizer referência ao assembly de componente usando
#using
, passe o atributoas_friend
. Se você especificar o atributoas_friend
para um assembly que não especificaInternalsVisibleToAttribute
, uma exceção de runtime será gerada se você tentar acessar um tipo no escopo do namespace ou no escopo global no componente.
O resultado será um erro de build se o assembly que contém o atributo InternalsVisibleToAttribute não tiver um nome forte, mas o assembly do cliente que usa o atributo as_friend
tiver.
Apesar da possibilidade de os tipos no escopo do namespace e no escopo global serem conhecidos por um assembly de cliente ou .netmodule, a acessibilidade do membro ainda estará em vigor. Por exemplo, você não pode acessar um membro privado.
O acesso a todos os tipos em um assembly deve ser explicitamente concedido. Por exemplo, o assembly C não tem acesso a todos os tipos no assembly A, se o assembly C fizer referência ao assembly B, e o assembly B tiver acesso a todos os tipos no assembly A.
Para obter informações sobre como assinar, ou seja, como dar um nome forte a, um assembly criado usando o compilador do Microsoft C++, confira Assemblies de nome forte (assinatura de assembly) (C++/CLI).
Como alternativa ao uso do recurso de assemblies amigáveis, você pode usar StrongNameIdentityPermission para restringir o acesso a tipos individuais.
Requisitos
Opção do compilador: /clr
Exemplos
O exemplo de código a seguir define um componente que especifica um assembly de cliente que tem acesso aos tipos no componente.
// 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");
}
};
O próximo exemplo de código acessa um tipo privado no componente.
// 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
O próximo exemplo de código define um componente, mas não especifica um assembly de cliente que terá acesso aos tipos no componente.
Observe que o componente é vinculado usando /opt:noref. Isso garante que os tipos privados sejam emitidos nos metadados do componente, o que não é necessário quando o atributo InternalsVisibleTo
está presente. Para obter mais informações, consulte /OPT (Otimizações).
// 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");
}
};
O exemplo de código a seguir define um cliente que tenta acessar um tipo privado em um componente que não dá acesso aos seus tipos privados. Devido ao comportamento do runtime, se você quiser capturar a exceção, tente acessar um tipo privado em uma função auxiliar.
// 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
O próximo exemplo de código mostra como criar um componente de nome forte que especifica um assembly de cliente que terá acesso aos tipos no componente.
// 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");
}
};
Observe que o componente deve especificar sua chave pública. Sugerimos que você execute os seguintes comandos sequencialmente em um prompt de comando para criar um par de chaves e obter a chave pública:
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
O próximo exemplo de código acessa um tipo privado no componente de nome forte.
// 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