Comment déclarer un assemblage ami?

114

J'ai 2 projets dans ma solution:

  1. Assemblage (bibliothèque de base)
  2. Assemblage de test (NUnit)

J'avais déclaré l'assemblage de test en tant qu'assemblage d'amis dans le premier projet:

[assembly: InternalsVisibleTo ("Company.Product.Tests")]

Tout fonctionnait bien jusqu'à ce que je réalise que j'ai oublié de configurer la solution pour signer mes assemblages. Vous avez donc créé un fichier snk et configuré le projet Visual Studio pour signer le premier assembly (Basic Library). Maintenant, lorsque je compile le premier projet, j'obtiens l'erreur suivante:

La référence d'assemblage d'ami «Company.Product.Tests» n'est pas valide. Les assemblys signés avec un nom fort doivent spécifier une clé publique dans leurs déclarations InternalsVisibleTo.

J'ai essayé d'extraire la clé publique de mon fichier snk à l'aide de l'utilitaire sn mais il génère un fichier binaire câblé que je ne sais pas comment utiliser. Comment puis-je résoudre le problème?

Hemant
la source

Réponses:

194

Vous devez signer les deux assemblys, car les deux assemblys se référencent effectivement.

Vous devez mettre la clé publique dans l'attribut InternalsVisibleTo. Par exemple, dans Protocol Buffers, j'utilise:

[assembly:InternalsVisibleTo("Google.ProtocolBuffers.Test,PublicKey="+
"00240000048000009400000006020000002400005253413100040000010001008179f2dd31a648"+
"2a2359dbe33e53701167a888e7c369a9ae3210b64f93861d8a7d286447e58bc167e3d99483beda"+
"72f738140072bb69990bc4f98a21365de2c105e848974a3d210e938b0a56103c0662901efd6b78"+
"0ee6dbe977923d46a8fda18fb25c65dd73b149a5cd9f3100668b56649932dadd8cf5be52eb1dce"+
"ad5cedbf")]

La clé publique est récupérée en exécutant

sn -Tp path\to\test\assembly.dll

Vous pouvez également l'obtenir à partir du fichier .snk:

sn -p MyStrongnameKey.snk public.pk
sn -tp public.pk
Jon Skeet
la source
7
Et il est extrêmement irritant de voir la documentation MSDN ( msdn.microsoft.com/en-us/library/… ) mentionner une clé publique ridiculement courte qui ressemble presque à un jeton de clé publique pour moi.
Hemant
3
Vous pouvez extraire la clé publique directement d'un fichier .snk: sn -k MyStrongnameKey.snk // sn -p MyStrongnameKey.snk public.pk // sn -tp public.pk //
Tim Long
1
J'utilisais le «titre d'assemblage» spécifié dans AssemblyInfo.cs. Depuis lors, le bon nom à utiliser est le `` nom de l'assembly '' de la boîte de dialogue Propriétés / Application du projet (qui diffère à nouveau du nom du projet dans l'explorateur de solutions de Visual Studio).
Colonel Panic
7
Aussi utiles que ces réponses et commentaires aient été, j'avais besoin de quelques expérimentations pour réaliser que la clé publique est celle de l'assembly contenant les tests, PAS l'assembly qui contient la déclaration 'InternalsInvisibleTo'.
Andreas
3
@Andreas: Eh bien, cela va de pair avec l'assembly que vous nommez - vous spécifiez le nom fort de l'assembly à approuver, dans l'assembly qui fait la confiance.
Jon Skeet
-3

Vous pouvez directement obtenir publicKey de l'assemblage qui vous intéresse, sans magie avec sn.exe

<!-- language: c# -->
var assemblyName = Assembly.GetExecutingAssembly().GetName();
Console.WriteLine("{0}, PublicKey={1}",
    assemblyName.Name,
string.Join("", assemblyName.GetPublicKey().Select(m => string.Format("{0:x2}", m))));
ezyuzin
la source
1
Ce n'est pas une réponse à cette question. Cela devrait être un commentaire sur la réponse à laquelle il s'adresse
Cole Johnson
-7

Je pense que vous devez mettre le nom fort, qui serait quelque chose comme "Company.Product.Tests, Version = 1.0.0.0, Culture = neutre, PublicKeyToken = 17135d9fcba0119f". Je suppose que Company.Product.Tests est le nom de votre assemblage et 17135d9fcba0119f est la clé publique.

Une autre façon de résoudre ce problème consiste à ne pas utiliser d'assemblys séparés. Je mets généralement le code source et le code de test dans le même assemblage. Je ne sais pas si vous craignez particulièrement de devoir les séparer.

utilisateur95319
la source
Je ne pense pas que nous devions spécifier le numéro de version et la culture (voir msdn.microsoft.com/en-us/library/… ). Je n'ai pas vraiment essayé de mettre le code de test dans l'assemblage lui-même. Je vais essayer de voir comment cela fonctionne (+1 pour le pourboire).
Hemant
4
Pour InternalsVisibleTo, PublicKeToken ne suffit pas. Vous avez besoin de la clé publique entière :-(
Sean Reilly