Compartilhar via


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

  1. 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.

  2. No assembly do cliente ou .netmodule, quando você fizer referência ao assembly de componente usando #using, passe o atributo as_friend. Se você especificar o atributo as_friend para um assembly que não especifica InternalsVisibleToAttribute, 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

Confira também

Extensões de componentes para plataformas de runtime