Friend-Assemblys (C++)
Für anwendbare Laufzeiten erstellt das Feature "Friend Assemblies Language" Typen, die sich im Namespacebereich oder globalen Bereich in einer Assemblykomponente befinden, auf die mindestens eine Clientassembly oder .netmodule zugegriffen werden kann.
Alle Laufzeiten
Anmerkungen
(Dieses Sprachfeature wird in allen Laufzeiten nicht unterstützt.)
Windows-Runtime
Anmerkungen
(Dieses Sprachfeature wird in der Windows-Runtime nicht unterstützt.)
Anforderungen
Compileroption: /ZW
Übersicht: Common Language Runtime (CLR)
Anmerkungen
So erstellen Sie Typen im Namespacebereich oder globalen Bereich in einer Assemblykomponente, auf die für eine Clientassembly oder .netmodule zugegriffen werden kann
Geben Sie in der Komponente ein Assembly-Attribut InternalsVisibleToAttributean, und übergeben Sie den Namen der Clientassembly oder .netmodule, die auf Typen im Namespacebereich oder globalen Bereich in der Komponente zugreifen. Sie können mehrere Clientassemblys oder .netmodule angeben, indem Sie zusätzliche Attribute angeben.
Übergeben Sie in der Clientassembly oder .netmodule, wenn Sie mithilfe
#using
der Verwendung auf die Komponentenassembly verweisen, dasas_friend
Attribut. Wenn Sie dasas_friend
Attribut für eine Assembly angeben, die nicht angegebenInternalsVisibleToAttribute
wird, wird eine Laufzeit ausnahme ausgelöst, wenn Sie versuchen, auf einen Typ im Namespacebereich oder globalen Bereich in der Komponente zuzugreifen.
Ein Buildfehler führt dazu, wenn die Assembly, die das InternalsVisibleToAttribute Attribut enthält, keinen starken Namen hat, aber die Clientassembly, die das as_friend
Attribut verwendet.
Obwohl Typen im Namespacebereich und globalen Bereich einer Clientassembly oder .netmodule bekannt sein können, ist die Barrierefreiheit von Membern weiterhin wirksam. Sie können beispielsweise nicht auf ein privates Mitglied zugreifen.
Der Zugriff auf alle Typen in einer Assembly muss explizit gewährt werden. Assembly C hat beispielsweise keinen Zugriff auf alle Typen in Assembly A, wenn Assembly C auf Assembly B und Assembly B Zugriff auf alle Typen in Assembly A hat.
Informationen zum Signieren – d. h. zum Zuweisen eines starken Namens – einer Assembly, die mithilfe des Microsoft C++-Compilers erstellt wird, finden Sie unter "Assemblysignierung mit starkem Namen" (C++/CLI).
Alternativ zur Verwendung der Funktion "Friend Assemblies" können StrongNameIdentityPermission Sie den Zugriff auf einzelne Typen einschränken.
Anforderungen
Compileroption: /clr
Beispiele
Im folgenden Codebeispiel wird eine Komponente definiert, die eine Clientassembly angibt, die Zugriff auf die Typen in der Komponente hat.
// 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");
}
};
Im nächsten Codebeispiel wird auf einen privaten Typ in der Komponente zugegriffen.
// 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
Im nächsten Codebeispiel wird eine Komponente definiert, aber keine Clientassembly angegeben, die Zugriff auf die Typen in der Komponente hat.
Beachten Sie, dass die Komponente mithilfe von /opt:noref verknüpft ist. Dadurch wird sichergestellt, dass private Typen in den Metadaten der Komponente ausgegeben werden, was nicht erforderlich ist, wenn das InternalsVisibleTo
Attribut vorhanden ist. Weitere Informationen finden Sie unter /OPT (Optimierungen).
// 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");
}
};
Im folgenden Codebeispiel wird ein Client definiert, der versucht, auf einen privaten Typ in einer Komponente zuzugreifen, die keinen Zugriff auf seine privaten Typen ermöglicht. Aufgrund des Verhaltens der Laufzeit müssen Sie versuchen, auf einen privaten Typ in einer Hilfsfunktion zuzugreifen, wenn Sie die Ausnahme abfangen möchten.
// 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
Das nächste Codebeispiel zeigt, wie Sie eine Komponente mit starkem Namen erstellen, die eine Clientassembly angibt, die Zugriff auf die Typen in der Komponente hat.
// 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");
}
};
Beachten Sie, dass die Komponente ihren öffentlichen Schlüssel angeben muss. Es wird empfohlen, die folgenden Befehle sequenziell an einer Eingabeaufforderung auszuführen, um ein Schlüsselpaar zu erstellen und den öffentlichen Schlüssel abzurufen:
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
Im nächsten Codebeispiel wird auf einen privaten Typ in der Komponente mit starkem Namen zugegriffen.
// 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