¿Cómo declarar una asamblea de amigos?

114

Tengo 2 proyectos en mi solución:

  1. Ensamblaje (biblioteca básica)
  2. Ensamblaje de prueba (NUnit)

Había declarado el ensamblaje de prueba como ensamblaje de amigos en el primer proyecto:

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

Todo funcionaba bien hasta que me di cuenta de que me había olvidado de configurar la solución para firmar mis ensamblajes. Así que creó un archivo snk y configuró el proyecto de Visual Studio para firmar el primer ensamblaje (Biblioteca básica). Ahora, cuando compilo el primer proyecto, aparece el siguiente error:

La referencia de ensamblado de un amigo "Company.Product.Tests" no es válida. Los ensamblados firmados con nombre seguro deben especificar una clave pública en sus declaraciones InternalsVisibleTo.

Intenté extraer la clave pública de mi archivo snk usando la utilidad sn, pero genera un archivo binario cableado que no estoy seguro de cómo usarlo. ¿Cómo puedo solucionar el problema?

Hemant
fuente

Respuestas:

194

Debe firmar ambos ensamblajes, porque efectivamente ambos ensamblajes hacen referencia entre sí.

Tienes que poner la clave pública en el atributo InternalsVisibleTo. Por ejemplo, en Protocol Buffers utilizo:

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

La clave pública se recupera ejecutando

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

Alternativamente, obténgalo del archivo .snk:

sn -p MyStrongnameKey.snk public.pk
sn -tp public.pk
Jon Skeet
fuente
7
Y es muy irritante ver que la documentación de MSDN ( msdn.microsoft.com/en-us/library/… ) menciona una clave pública ridículamente corta que casi me parece un token de clave pública .
Hemant
3
Puede extraer la clave pública directamente de un archivo .snk: sn -k MyStrongnameKey.snk // sn -p MyStrongnameKey.snk public.pk // sn -tp public.pk //
Tim Long
1
Estaba usando el 'título de ensamblaje' especificado en AssemblyInfo.cs. Desde entonces, el nombre correcto para usar es el 'nombre de ensamblado' del cuadro de diálogo Propiedades / Aplicación del proyecto (que nuevamente difiere del nombre del proyecto en el explorador de soluciones de Visual Studio).
Coronel Panic
7
Por muy útiles que hayan sido estas respuestas y comentarios, necesité un poco de experimentación para darme cuenta de que la clave pública es la del ensamblado que contiene las pruebas, NO el ensamblado que contiene la declaración 'InternalsInvisibleTo'.
Andreas
3
@Andreas: Bueno, va junto con el ensamblado que está nombrando: está especificando el nombre seguro del ensamblado en el que confiar, dentro del ensamblado que está confiando.
Jon Skeet
-3

Puede obtener directamente publicKey del ensamblaje que le interese, sin magia con 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
fuente
1
Esta no es una respuesta a esta pregunta. Debería ser un comentario sobre la respuesta a la que se dirige
Cole Johnson
-7

Creo que debe ingresar el nombre seguro, que sería algo así como "Company.Product.Tests, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = 17135d9fcba0119f". Supongo que Company.Product.Tests es su nombre de ensamblado y 17135d9fcba0119f es la clave pública.

Otra forma de resolver este problema sería no utilizar ensamblajes separados. Normalmente pongo el código fuente y el código de prueba en el mismo ensamblado. No sé si tiene alguna preocupación especial de que deba separarlos.

usuario95319
fuente
No creo que debamos especificar el número de versión y la cultura (consulte msdn.microsoft.com/en-us/library/… ). Realmente no he intentado poner el código de prueba en el ensamblaje. Intentaré ver cómo funciona (+1 para la propina).
Hemant
4
Para InternalsVisibleTo, PublicKeToken no es suficiente. Necesita la clave pública completa :-(
Sean Reilly