Pregunta

Estoy tratando de usar el InternalsVisibleTo atributo de ensamblaje para hacer que mis clases internas en una biblioteca de clases .NET sean visibles para mi proyecto de prueba unitaria.Por alguna razón, sigo recibiendo un mensaje de error que dice:

'MyClassName' es inaccesible debido a su nivel de protección

Ambos ensamblajes están firmados y tengo la clave correcta en la declaración de atributos.¿Algunas ideas?

¿Fue útil?

Solución

¿Está absolutamente seguro de que tiene la clave pública correcta especificada en el atributo?Tenga en cuenta que debe especificar la clave pública completa, no solo el token de clave pública.Se parece a algo así:

[assembly: InternalsVisibleTo("MyFriendAssembly,
PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73
F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66
A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519
674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C140
6E2F553073FF557D2DB6C5")]

Son aproximadamente 320 dígitos hexadecimales.No estoy seguro de por qué necesita especificar la clave pública completa; posiblemente, con solo el token de clave pública que se usa en otras referencias del ensamblado, sería más fácil para alguien falsificar la identidad del ensamblado amigo.

Otros consejos

Otro posible "te pillé":El nombre de la asamblea de amigos que especifica en el InternalsVisibleToAttribute debe exactamente coincida con el nombre del ensamblaje de su amigo como se muestra en las propiedades del proyecto del amigo (en la pestaña Aplicación).

En mi caso, tenía un proyecto. Thingamajig y un proyecto complementario ThingamajigAutoTests (nombres cambiados para proteger a los culpables) que ambos produjeron asambleas sin firmar.Agregué debidamente el atributo [assembly: InternalsVisibleTo( "ThingamajigAutoTests" )] al archivo Thingamajig\AssemblyInfo.cs y comente el archivo AssemblyKeyFile y AssemblyKeyName atributos como se indicó anteriormente.El Thingamajig El proyecto se construyó bien, pero sus miembros internos se negaron obstinadamente a aparecer en el proyecto de prueba automática.

Después de rascarme mucho la cabeza, volví a comprobar el ThingamajigAutoTests propiedades del proyecto y descubrió que el nombre del ensamblado estaba especificado como "ThingamajigAutoTests.dll".Bingo: agregué la extensión ".dll" al nombre del ensamblado en el InternalsVisibleTo atributo, y las piezas encajaron en su lugar.

A veces son las cosas más pequeñas...

Si sus ensamblados no están firmados, pero aún recibe el mismo error, revise su archivo AssemblyInfo.cs para ver cualquiera de las siguientes líneas:

[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

La pestaña de propiedades seguirá mostrando su ensamblaje como sin firmar si una de estas líneas (o ambas) están presentes, pero el atributo InternalsVisibleTo trata un ensamblaje con estas líneas como fuertemente firmado.Simplemente elimine (o comente) estas líneas y debería funcionar bien para usted.

Vale la pena señalar que si el ensamblado "amigo" (pruebas) está escrito en C++/CLI, en lugar de C#/VB.Net, entonces necesita usar lo siguiente:

#using "AssemblyUnderTest.dll" as_friend

en lugar de una referencia de proyecto o lo habitual #using declaración.Por alguna razón, no hay forma de hacer esto en la interfaz de usuario de referencia del proyecto.

Puedes usar Herramienta auxiliar de montaje eso generará la sintaxis de InternalsVisibleTo para usted.Aquí está el enlace a la última versión.Solo tenga en cuenta que solo funciona para ensamblados con nombres seguros.

Aquí hay una macro que uso para generar rápidamente este atributo.Es un poco complicado, pero funciona.En mi máquina.Cuando el último binario firmado está en /bin/debug.Etc. equivocaciones, etc.De todos modos, puedes ver cómo obtiene la clave, eso te dará una pista.Arregle/mejore según lo permita su tiempo.

Sub GetInternalsVisibleToForCurrentProject()
    Dim temp = "[assembly:  global::System.Runtime.CompilerServices." + _
               "InternalsVisibleTo(""{0}, publickey={1}"")]"
    Dim projs As System.Array
    Dim proj As Project
    projs = DTE.ActiveSolutionProjects()
    If projs.Length < 1 Then
        Return
    End If

    proj = CType(projs.GetValue(0), EnvDTE.Project)
    Dim path, dir, filename As String
    path = proj.FullName
    dir = System.IO.Path.GetDirectoryName(path)
    filename = System.IO.Path.GetFileNameWithoutExtension(path)
    filename = System.IO.Path.ChangeExtension(filename, "dll")
    dir += "\bin\debug\"
    filename = System.IO.Path.Combine(dir, filename)
    If Not System.IO.File.Exists(filename) Then
        MsgBox("Cannot load file " + filename)
        Return
    End If
    Dim assy As System.Reflection.Assembly
    assy = System.Reflection.Assembly.Load(filename)
    Dim pk As Byte() = assy.GetName().GetPublicKey()
    Dim hex As String = BitConverter.ToString(pk).Replace("-", "")
    System.Windows.Forms.Clipboard.SetText(String.Format(temp, assy.GetName().Name, hex))
    MsgBox("InternalsVisibleTo attribute copied to the clipboard.")
End Sub

Necesitas usar /out:Interruptor del compilador Al compilar el ensamblaje de amigos (el ensamblaje que no contiene el atributo internovisibleto).

El compilador necesita saber el nombre del ensamblado que se está compilando para determinar si el ensamblado resultante debe considerarse un ensamblado amigo.

Además de todo lo anterior, cuando todo parece estar correcto, pero la asamblea amiga se niega obstinadamente a ver el interior, recargar la solución o reiniciar Visual Studio puede resolver el problema.

En mi caso usando VS.Net 2015, necesitaba firmar AMBOS ensamblajes (si se firma al menos 1 ensamblaje o desea hacer referencia a la clave pública de su ensamblaje).

Mi proyecto no utilizó la firma en absoluto.Entonces comencé a agregar una clave de signo a mi biblioteca de prueba y a usar InternalsVisibleTo-Attribute en la biblioteca base de mi proyecto.Pero VS.Net siempre explicó que no podía acceder a los métodos amigos.

Cuando comencé a firmar la biblioteca base (puede ser la misma clave de firma u otra, siempre y cuando firme la biblioteca base), VS.Net pudo funcionar inmediatamente como se esperaba.

Las respuestas anteriores con PublicKey funcionaron:(Estudio visual 2015:NECESITA estar en una línea; de lo contrario, se queja de que la referencia del ensamblado no es válida o no se puede hacer referencia a ella.PublicKeyToken no funcionó)

[assembly: InternalsVisibleTo("NameSpace.MyFriendAssembly, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C1406E2F553073FF557D2DB6C5")]

Gracias a @Joe

Para obtener la clave pública del ensamblaje amigo:

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

Dentro de un símbolo del sistema del desarrollador (Inicio > Programas > Visual Studio 2015 > Visual Studio Tools > Símbolo del sistema del desarrollador para VS2015).Gracias a @Ian G.

Aunque, el toque final que hizo que me funcionara después de lo anterior fue firmar el proyecto de la biblioteca de mi amigo de la misma manera que se firma el proyecto de la biblioteca para compartir.Como era una nueva biblioteca de prueba, aún no estaba firmada.

Debe generar una nueva clave pública completa para el ensamblado y luego especificar el atributo para el ensamblado.

[assembly: InternalsVisibleTo("assemblyname,
PublicKey="Full Public Key")]

Sigue lo siguiente MSDN Pasos para generar una nueva clave pública completa para el ensamblaje desde Visual Studio.

Para agregar un elemento Obtener clave pública de ensamblaje al menú Herramientas

En Visual Studio, haga clic en Herramientas externas en el menú Herramientas.

En el cuadro de diálogo Herramientas externas, haga clic en Agregar e ingrese Obtener clave pública de ensamblaje en el cuadro Título.

Complete el cuadro Comando navegando hasta sn.exe.Normalmente se instala en la siguiente ubicación: C:\Archivos de programa (x86)\Microsoft SDKs\Windows\v7.0a\Bin\x64\sn.exe.

En el cuadro Argumentos, escriba lo siguiente (distingue entre mayúsculas y minúsculas): -Tp $(Ruta de destino).Seleccione la casilla de verificación Usar ventana de salida.

Hacer clic DE ACUERDO.El nuevo comando se agrega al menú Herramientas.

Siempre que necesite el token de clave pública del ensamblaje que está desarrollando, haga clic en el comando Obtener clave pública del ensamblaje en el menú Herramientas y el token de clave pública aparecerá en la ventana Salida.

Otra posibilidad que puede resultar difícil de detectar, dependiendo de cómo esté escrito el código.

  1. Estás invocando un método interno definido en X desde otro ensamblado Y
  2. La firma del método utiliza tipos internos definidos en Z.
  3. Luego tienes que agregar [InternalsVisibleTo] en X Y en Z

Por ejemplo:

// In X
internal static class XType
{
    internal static ZType GetZ() { ... }
}

// In Y:
object someUntypedValue = XType.GetZ();

// In Z:
internal class ZType { ... }

Si lo tiene escrito como arriba, donde no se refiere a ZType directamente en Y, después de haber agregado Y como amigo de X, es posible que se sienta desconcertado por qué su código aún no se compila.

El error de compilación definitivamente podría ser más útil en este caso.

Se aplica solo si desea mantener los ensamblados sin firmar como ensamblados sin firmar (y no desea firmarlos por varias razones):

Todavía hay otro punto:Si compila su biblioteca base desde VS.Net en un directorio local, es posible que funcione como se esperaba.

PERO:Tan pronto como compila su biblioteca base en una unidad de red, se aplican las políticas de seguridad y el ensamblaje no se puede cargar correctamente.Esto nuevamente hace que VS.NET o el compilador fallen al verificar la coincidencia de PublicKey.

FINALMENTE, es posible utilizar ensamblados sin firmar:https://msdn.microsoft.com/en-us/library/bb384966.aspxDebe asegurarse de que ambos ensamblados no estén firmados y que el atributo de ensamblaje debe estar sin información de clave pública:

<Assembly: InternalsVisibleTo("friend_unsigned_B")>

Estoy escribiendo esto por frustración.Asegúrese de que el ensamblaje al que está otorgando acceso tenga el nombre esperado.

Cambié el nombre de mi proyecto pero esto no actualiza automáticamente el nombre del ensamblaje.Haga clic derecho en su proyecto y haga clic Propiedades.Bajo Solicitud, asegúrese de que el Nombre de la Asamblea y Espacio de nombres predeterminado son lo que esperas.

Yo tuve el mismo problema.Ninguna de las soluciones funcionó.

Finalmente descubrí que el problema se debía a que la clase X implementaba explícitamente la interfaz Y, que es interna.

el método X.InterfaceMethod no estaba disponible, aunque no tengo idea de por qué.

La solución fue convertir (X as YourInterface).InterfaceMethod en la biblioteca de prueba, y luego todo funcionó.

Como nota al margen, si desea obtener fácilmente la clave pública sin tener que usar sn y descubrir sus opciones, puede descargar el práctico programa. aquí.No sólo determina la clave pública sino que también crea el "ensamblado:InternalsVisibleTo..." línea lista para ser copiada en el portapapeles y pegada en su código.

Acabo de resolver un problema similar con el InternalsVisibleTo Atributo.Todo parecía estar bien y no podía entender por qué la clase interna a la que apuntaba todavía no era accesible.

Cambiar el caso de la clave de mayúsculas a minúsculas solucionó el problema.

Si tiene más de un ensamblaje al que se hace referencia, verifique que todos los ensamblajes necesarios tengan el atributo InternalsVisibleTo.A veces no es obvio y no aparece ningún mensaje de que debe agregar este atributo en otro ensamblaje.

1- Firma el proyecto de prueba: En Visual Studio, vaya a la ventana de propiedades de el proyecto de prueba y Firmar la asamblea marcando la casilla con la misma frase en el Firma pestaña.

2- Cree una clave pública para el proyecto de prueba: Abra el símbolo del sistema de Visual Studio (p. ej.Símbolo del sistema del desarrollador para VS 2017).Vaya a la carpeta donde se encuentra el archivo .dll de el proyecto de prueba existe.Cree una clave pública a través de sn.exe:

sn -Tp TestProject.dll

Tenga en cuenta que el argumento es -Tp, pero no -tp.

3- Introducir la PublicKey al proyecto a probar: Vaya al archivo AssemblyInfo.cs en el proyecto a probar y agrega esta línea con la PublicKey creada en el paso anterior:

[asamblea:InternosVisibleTo("Nombre del conjunto del proyecto de prueba, Llave pública=2066212d128683a85f31645c60719617ba512c0bfdba6791612ed56350368f6cc40a17b4942ff16cda9e760684658fa3f357c137a1005b04cb00240000048000009 4000000060200000024000052534131000400000100010065fe67a14eb30ffcdd99880e9d725f04e5c720dffc561b23e2953c34db8b7c5d4643f476408ad1b1e28d6 bde7d64279b0f51bf0e60be2d383a6c497bf27307447506b746bd2075")]

No olvide reemplazar la PublicKey anterior por la suya.

4- Haz que el método privado sea interno: En el proyecto a probar, cambie el modificador de acceso del método a interno.

estática interna void Hacer algo(){...}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top