Assembly Friend (C++)
Per i runtime applicabili, la funzionalità del linguaggio friend assembly rende i tipi che si trovano nell'ambito dello spazio dei nomi o nell'ambito globale in un componente assembly accessibile a uno o più assembly client o .netmodules.
Tutti i runtime
Osservazioni:
Questa funzionalità del linguaggio non è supportata in tutti i runtime.
Windows Runtime
Osservazioni:
Questa funzionalità del linguaggio non è supportata in Windows Runtime.
Requisiti
Opzione del compilatore: /ZW
Common Language Runtime
Osservazioni:
Per rendere i tipi nell'ambito dello spazio dei nomi o nell'ambito globale in un componente assembly accessibile a un assembly client o a .netmodule
Nel componente specificare un attributo InternalsVisibleToAttributeassembly e passare il nome dell'assembly client o .netmodule che accederà ai tipi nell'ambito dello spazio dei nomi o nell'ambito globale del componente. È possibile specificare più assembly client o .netmodules specificando attributi aggiuntivi.
Nell'assembly client o in .netmodule, quando si fa riferimento all'assembly del componente usando
#using
, passare l'attributoas_friend
. Se si specifica l'attributo per un assembly che non specificaInternalsVisibleToAttribute
, verrà generata un'eccezione di runtime se si tenta di accedere a un tipo nell'ambitoas_friend
dello spazio dei nomi o nell'ambito globale nel componente.
Se l'assembly che contiene l'attributo InternalsVisibleToAttribute non ha un nome sicuro ma l'assembly client che usa l'attributo as_friend
, verrà generato un errore di compilazione.
Anche se i tipi nell'ambito dello spazio dei nomi e nell'ambito globale possono essere noti a un assembly client o a .netmodule, l'accessibilità dei membri è ancora attiva. Ad esempio, non è possibile accedere a un membro privato.
L'accesso a tutti i tipi in un assembly deve essere concesso in modo esplicito. Ad esempio, l'assembly C non ha accesso a tutti i tipi nell'assembly A se l'assembly C fa riferimento all'assembly B e l'assembly B ha accesso a tutti i tipi nell'assembly A.
Per informazioni su come firmare, ovvero come assegnare un nome sicuro a , un assembly compilato usando il compilatore Microsoft C++, vedere Assembly con nome sicuro (firma di assembly) (C++/CLI).
In alternativa all'uso della funzionalità di assembly Friend, è possibile usare StrongNameIdentityPermission per limitare l'accesso ai singoli tipi.
Requisiti
Opzione del compilatore: /clr
Esempi
Nell'esempio di codice seguente viene definito un componente che specifica un assembly client che ha accesso ai tipi nel 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");
}
};
L'esempio di codice successivo accede a un tipo privato nel 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
L'esempio di codice successivo definisce un componente, ma non specifica un assembly client che avrà accesso ai tipi nel componente.
Si noti che il componente è collegato tramite /opt:noref. In questo modo si garantisce che i tipi privati vengano generati nei metadati del componente, che non sono necessari quando l'attributo InternalsVisibleTo
è presente. Per altre informazioni, vedere /OPT (Ottimizzazioni).
// 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");
}
};
Nell'esempio di codice seguente viene definito un client che tenta di accedere a un tipo privato in un componente che non concede l'accesso ai tipi privati. A causa del comportamento del runtime, se si vuole intercettare l'eccezione, è necessario tentare di accedere a un tipo privato in una funzione 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");
}
}
caught an exception
Nell'esempio di codice seguente viene illustrato come creare un componente con nome sicuro che specifica un assembly client che avrà accesso ai tipi nel 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");
}
};
Si noti che il componente deve specificare la chiave pubblica. È consigliabile eseguire i comandi seguenti in sequenza al prompt dei comandi per creare una coppia di chiavi e ottenere la chiave pubblica:
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
L'esempio di codice successivo accede a un tipo privato nel componente con nome sicuro.
// 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