Partager via


Assemblys friend (C++)

Pour les runtimes applicables, la fonctionnalité de langage des assemblys friend rend les types qui se trouvent dans l’étendue de l’espace de noms ou l’étendue globale d’un composant d’assembly accessible à un ou plusieurs assemblys clients ou .netmodules.

Tous les runtimes

Remarques

(Cette fonctionnalité de langage n’est pas prise en charge dans tous les runtimes.)

Windows Runtime

Remarques

(Cette fonctionnalité de langage n’est pas prise en charge dans Windows Runtime.)

Spécifications

Option du compilateur : /ZW

Common Language Runtime

Remarques

Pour rendre les types au niveau de l’étendue de l’espace de noms ou de l’étendue globale dans un composant d’assembly accessible à un assembly client ou à .netmodule

  1. Dans le composant, spécifiez un attribut InternalsVisibleToAttributed’assembly et transmettez le nom de l’assembly client ou .netmodule qui accède aux types au niveau de l’étendue de l’espace de noms ou de l’étendue globale dans le composant. Vous pouvez spécifier plusieurs assemblys clients ou .netmodules en spécifiant des attributs supplémentaires.

  2. Dans l’assembly client ou .netmodule, lorsque vous référencez l’assembly de composant à l’aide #usingde , passez l’attribut as_friend . Si vous spécifiez l’attribut d’un assembly qui ne spécifie InternalsVisibleToAttributepas, une exception d’exécution est levée si vous essayez d’accéder à un type au niveau de l’étendue as_friend de l’espace de noms ou de l’étendue globale dans le composant.

Une erreur de génération se produit si l’assembly qui contient l’attribut InternalsVisibleToAttribute n’a pas de nom fort, mais si l’assembly client qui utilise l’attribut le as_friend fait.

Bien que les types dans l’étendue de l’espace de noms et l’étendue globale puissent être connus pour un assembly client ou .netmodule, l’accessibilité des membres est toujours en vigueur. Par exemple, vous ne pouvez pas accéder à un membre privé.

L’accès à tous les types d’un assembly doit être accordé explicitement. Par exemple, l’assembly C n’a pas accès à tous les types dans l’assembly A si l’assembly C référence l’assembly B et l’assembly B a accès à tous les types dans l’assembly A.

Pour plus d’informations sur la façon de signer, autrement dit, comment attribuer un nom fort à un assembly généré à l’aide du compilateur Microsoft C++, consultez Assemblys de nom fort (signature d’assembly) (C++/CLI) .

En guise d’alternative à l’utilisation de la fonctionnalité d’assemblys friend, vous pouvez utiliser StrongNameIdentityPermission pour restreindre l’accès à des types individuels.

Spécifications

Option du compilateur : /clr

Exemples

L’exemple de code suivant définit un composant qui spécifie un assembly client qui a accès aux types du composant.

// 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’exemple de code suivant accède à un type privé dans le composant.

// 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’exemple de code suivant définit un composant, mais ne spécifie pas d’assembly client qui aura accès aux types du composant.

Notez que le composant est lié à l’aide de /opt :noref. Cela garantit que les types privés sont émis dans les métadonnées du composant, ce qui n’est pas obligatoire lorsque l’attribut InternalsVisibleTo est présent. Pour plus d’informations, consultez /OPT (Optimisations).

// 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");
   }
};

L’exemple de code suivant définit un client qui tente d’accéder à un type privé dans un composant qui ne donne pas accès à ses types privés. En raison du comportement du runtime, si vous souhaitez intercepter l’exception, vous devez tenter d’accéder à un type privé dans une fonction d’assistance.

// 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

L’exemple de code suivant montre comment créer un composant de nom fort qui spécifie un assembly client qui aura accès aux types du composant.

// 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");
   }
};

Notez que le composant doit spécifier sa clé publique. Nous vous suggérons d’exécuter les commandes suivantes de manière séquentielle à l’invite de commandes pour créer une paire de clés et obtenir la clé publique :

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’exemple de code suivant accède à un type privé dans le composant de nom fort.

// 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

Voir aussi

Extensions de composant pour les plateformes Runtime