el Guille, la Web del Visual Basic, C#, .NET y más...

Ensamblados amigos en Visual Basic (y C#)

 

En este artículo se cubren estos temas:
Crear ensamblados amigos con Visual Basic 2005
Usar los ensamblados amigos desde Visual C# 2005 (C# 2.0 o superior)
Usar los ensamblados amigos desde Visual Basic 9.0 (la que se incluye en Visual Studio Orcas)
Crear ficheros de claves para firmar los ensamblados con nombre seguro.
Generar la clave pública de un fichero de claves.

 

Publicado el 11/Abr/2007
Actualizado el 11/Abr/2007
Autor: Guillermo 'guille' Som

Los ensamblados amigos nos permiten acceder a elementos declarados con Friend (internal en C#) en otro ensamblado. Esos elementos amigos pueden ser clases o miembros de las clases que tengan ese modificador amigo.

 


 

Introducción:

En Visual Basic 9.0 (la versión que se incluye con Visual Studio Orcas o que usa el .NET Framework 3.5, como prefieras), permite el uso de lo que se conoce como ensamblados amigos, aunque Visual Basic 2005 nos permite crear ensamblados amigos para usarlos tanto desde C# 2.0 o superior o desde Visual Basic 9.0 (Orcas).

El acceso a los ensamblados amigos nos permite poder indicar en un ensamblado que otros ensamblados pueden acceder a los elementos declarados como "amigos", en Visual Basic se definen con Friend y en C# con internal.

Como sabes, todos los miembros declarados con Friend/internal solo son visibles y por tanto accesibles desde el mismo ensamblado, si quisieras usar cualquiera de esos elementos "amigos" desde otro ensamblado diferente, no podrías, ya que para ese otro ensamblado externo, no son visibles.

En C# 2.0 (Visual C# 2005) se pueden definir y usar ese tipo de ensamblados. Incluso con Visual Basic 2005 también se pueden definir los ensamblados amigos, pero no se pueden usar.

Por tanto, un ensamblado "amigable" se puede definir tanto en Visual Basic 2005 como en C# 3.0, pero para usarlo solo podemos usar C#.

Al menos hasta la versión 2005 de Visual Studio, ya que la próxima versión de Visual Studio Orcas si permite que Visual Basic sea un "consumidor" de ensamblados amigos.

No voy a entrar en la "ética" de si eso es... conveniente o no... de esto te hablo en Los ensamblados amigos o la ética al alcance de los programadores. Aquí solo te voy a explicar cómo definir ese tipo de ensamblado amigo y cómo usarlo.

 

Definir un ensamblado amigo

Imagina que tienes una librería de clases (o cualquier otro tipo de proyecto) en el que defines ciertas clases como Friend (internal en C#), e incluso algunas clases que son públicas en las que defines algunos métodos o propiedades como "amigas".

Pues bien, esos "elementos" definidos como Friend/internal solo los podrás acceder desde el mismo ensamblado en el que los has definido. Pero desde otro ensamblado no podrás, ya que al ser "internos", no son visibles de forma pública.

Ahora imagina que te planteas lo siguiente: Esos miembros o clases "internas" las quiero usar desde otro ensamblado (ya sea DLL o EXE).

Aquí es donde entra en juego los ensamblados amigos.

Ahora (con las versiones de Visual Studio 2005 o .NET Framework 2.0), puedes indicar que esas clases se usen desde otros ensamblados.

Para hacerlo, tendrás que añadir un atributo del tipo InternalsVisibleTo al ensamblado que define los miembros "amigos". Esa clase está definida en el espacio de nombres System.Runtime.CompilerServices y se debe aplicar a nivel del ensamblado completo, por tanto, el mejor sitio para ponerlo es en el fichero AssemblyInfo (pero como ahora suele estar oculto), mejor lo pones en una de las clases que tienes en tu ensamblado.

Si lo usas desde C#, procura que esté fuera de cualquier definición de espacios de nombres, y si lo usas desde Visual Basic, pues lo pones después de todos los Imports que tengas en la clase.

Esta sería la forma de definirlo tanto en Visual Basic como en C#:

Imports System.Runtime.CompilerServices

<Assembly: InternalsVisibleTo("Nombre_del_ensamblado_amigo, PublicKey=la clave pública")> 
using System.Runtime.CompilerServices;
 
[assembly: InternalsVisibleTo("Nombre_del_ensamblado_amigo, PublicKey=la clave pública")]

En el nombre del ensamblado, debes poner el nombre del ensamblado desde el que vas a usar las clases y miembros "internos" de este ensamblado. En la clave pública debes poner la ristra de números de la clave pública del ensamblado con el que quieres tener "amistad".

Los dos ensamblados deben estar firmados con nombre seguro. Y precisamente esa clave pública es la clave pública con la que está firmado el ensamblado que quieres "amigar".

 

Una vez que has hecho esa definición de el ensamblado que quieres que sea "amigo", desde ese otro ensamblado podrás acceder a los miembros definidos con Friend/internal.

Nota:
Puedes definir tantos ensamblados amigos como quieras, es decir, puedes usar varios assembly: InternalsVisibleTo con los nombres y claves públicas que quieras que puedan acceder a los miembros "internos" de tu ensamblado.
Pero recuerda que si usas Visual Basic 2005 solo puedes definirlos como amigos, pero no usarlos.

Pero como te he comentado antes, si estás usando Visual Basic 2005, solo puedes definir el ensamblado "amigable", pero no usarlo. Sin embargo con Visual C# 2005 (o si lo prefieres con C# 2.0) si que puedes definir y usar ensamblados amigos.

Para poder usar ensamblados amigos con Visual Basic, debes tener la versión 9.0 o sea, la que se incluye con Visual Studio Orcas., que algunos llaman Visual Studio 2007, pero... no se yo si estará listo antes de que acabe el año...

 

Un ejemplo de todo lo aquí comentado

Para probar todo esto que te digo, te voy a explicar los pasos que debes seguir.

Primero te explicaré cómo definir un ensamblado amigo desde Visual Basic 2005, el cual podrás usar desde C# 2005, ya que, como te he dicho antes, desde Visual Basic 2005 solo podemos crear ensamblados amigos, pero no podemos usarlos.

Después te voy a explicar cómo usar ese ensamblado desde Visual Basic 9.0 (para ello necesitarás Visual Studio Orcas).

Crear un ensamblado amigo con Visual Basic 2005

Abre el Visual Studio 2005 (no he probado con Visual Basic 2005 Express, y es posible que también sea válido, pero no lo he probado), y crea un nuevo proyecto de tipo Biblioteca de clases.
En el nombre le dices que se llame: InternalsVisibleTo01_vb.

En la clase por defecto que se crea, escribe todo este código (copia y pega):

' Prueba de InternalsVisibleTo                                      (11/Abr/07)

Imports System.Runtime.CompilerServices

<Assembly: InternalsVisibleTo("InternalsVisibleTo02_cs, PublicKey=00240000048...")> 
<Assembly: InternalsVisibleTo("InternalsVisibleTo03_cs, PublicKey=00240000048...")> 

' Las clases, métodos o propiedades, etc. Friend (internal en C#) solo serán visibles
' para los ensamblados externos que se indiquen con InternalsVisibleTo.
Public Class Class1
    Private m_Nombre As String

    Friend Property Nombre() As String
        Get
            Return m_Nombre
        End Get
        Set(ByVal value As String)
            m_Nombre = value
        End Set
    End Property

    Public Function Saludo() As String
        Return "Hola desde Class1.Saludo de Visual Basic"
    End Function

    Friend Function Saludo2() As String
        Return "Hola desde Class1.Saludo2 de Visual Basic"
    End Function
End Class

' Esta clase solo será visible si se usa InternalsVisibleTo
Friend Class Class2
    Public Function Saludo() As String
        Return "Hola desde Class2.Saludo de Visual Basic"
    End Function

    Friend Function Saludo2() As String
        Return "Hola desde Class2.Saludo2 de Visual Basic"
    End Function

End Class

Nota:
Fíjate que en PublicKey no he puesto la ristra completa de la clave pública, eso lo tendrás que hacer tú, dependiendo de la clave usada para firmar esos ensamblados.

Fíjate en el código anterior. En la clase Class1 he definido la propiedad Nombre como Friend, lo mismo que el método Saludo2. Y la clase Class2 está definida como Friend, lo mismo que el método Saludo2 de esa clase.

Si no puedes acceder a los ensamblados amigos, esos "elementos" definidos como Friend solo serán accesibles a otras clases que estén en ese mismo proyecto. Y cuando digo proyecto, me refiero a proyecto, no a solución, ya que una solución es un grupo de varios proyectos.

 

Firmar el ensamblado con nombre seguro (strong name)

Este ensamblado debe estar firmado con nombre seguro, por tanto, vamos a dejar que sea el propio Visual Studio el que defina una clave para esa firma.

En las propiedades del proyecto, (haciendo doble clic en My Project), selecciona la ficha Signing (no se como se llama en español, pero te puedes hacer una idea con la figura 1).

Figura 1. Firmar el ensamblado con nombre seguro
Figura 1. Firmar el ensamblado con nombre seguro

Marca la casilla Sign the assembly (firmar el ensamblado), y de la lista despegable, selecciona <New...> (nuevo), te mostrará otro cuadro de diálogo (como el de la figura 2).

Figura 2. Crear una clave de nombre seguro
Figura 2. Crear una clave de nombre seguro

Escribe Prueba.snk y quita la marca de "Protect my key..." (o haz lo que quieras, pero yo la he quitado).
Pulsa en OK y se creará el fichero con las claves a usar para firmar el ensamblado con nombre seguro.

Nota:
Si ya tienes una clave creada, la puedes usar, y lo que tendrías que hacer es usar <Browse...> en el paso de la figura 1, buscarías el fichero y se haría una copia en tu proyecto.

Cuando compiles ese ensamblado, se firmará con el nombre seguro (strong name) que has indicado y estará listo para ser usado.

 

Una vez que has seguido estos pasos, ya tienes un ensamblado que permite "la amistad entre otros ensamblados", esa amistad la tendrá con los ensamblados que hayas indicado en los atributos <Assembly: InternalsVisibleTo.

 

Ahora vamos a crear un proyecto en C# que use ese ensamblado amigo.

Crear un proyecto en C# para usar el ensamblado amigo

 

Nota:
Si tienes el Visual Studio 2005, puedes añadir un nuevo proyecto a la solución actual.
Si tienes el Visual C# 2005 Express, debes crear un nuevo proyecto y seguir estos mismos pasos, aunque en el caso de añadir una nueva referencia, debes buscar el ensamblado que antes se ha generado.

Crea un nuevo proyecto de Visual C# 2005 que sea de tipo consola, y dale el nombre InternalsVisibleTo02_cs.

En las referencias, (References) pulsa en Add Reference... (agregar referencia).
Te mostrará un cuadro de diálogo con varias fichas, selecciona la ficha "Projects" (proyectos), te mostrará los proyectos que tienes en la solución, por tanto, selecciona el que hemos creado antes.

Este proyecto (ensamblado) debe estar firmado con nombre seguro, por tanto, o bien usas un fichero de claves que ya tengas, o bien creas uno nuevo siguiendo los pasos que te he indicado antes.

Para simplificar, crea un nuevo fichero de claves que se llame PruebaCS.snk (ya sabes los pasos que debes dar).

Una cosa IMPORTANTE es que la clave pública de este ensamblado debe ser la misma que hemos indicado en el proyecto anterior.

Ahora te explico cómo hacerlo.

Para probar las clases que hemos definido en el proyecto anterior, escribe el siguiente código:

using System;
using System.Collections.Generic;
using System.Text;

using InternalsVisibleTo01_vb;

namespace InternalsVisibleTo02_cs
{
    class Program
    {
        static void Main(string[] args)
        {
            Class1 c1 = new Class1();
            c1.Nombre = "elGuille";
            Console.WriteLine(c1.Nombre);
            Console.WriteLine(c1.Saludo());
            Console.WriteLine(c1.Saludo2());

            Class2 c2 = new Class2();
            Console.WriteLine(c2.Saludo());
            Console.WriteLine(c2.Saludo2());

            Console.ReadKey();
        }
    }
}

Si pruebas a compilar este proyecto (haz que sea el predeterminado), seguramente te dará error diciéndote que Nombre es privado, que Class2 es privada, etc.

Ese es el comportamiento "normal" para ensamblados que no son "amigos".

Para que este ensamblado se "confraterne" con el otro, (puedes hacer que los dos se vayan de copas), (ya está el otro Guille molestando...) debemos averiguar cual es la clave pública con la que acabamos de firmar este proyecto y usar ese valor en el proyecto anterior.

 

Averiguar la clave pública de un fichero de claves

Si has seguido los pasos que te he recomendado, el proyecto de C# lo habrás firmado con un fichero de claves llamado PruebaCS.snk.

Ahora vamos a averiguar la clave pública que tiene ese fichero para usarlo en el proyecto de Visual Basic.

Abre el acceso directo a la línea de comandos de Visual Studio 2005, o la ventana de comandos que te permita acceder al fichero sn.exe.

En mi instalación de Windows Vista con Visual Studio 2005 y el SDK de Windows 6.0 (el que sirve para usar el .NET Framework 3.0), lo tengo en: C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin, pero es posible que lo tengas en C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin.

Sea como sea, procura poder ejecutar sn y que no te de error.

En esa ventana de comandos, cambia a la unidad y directorio donde tengas el proyecto de C# que acabas de crear.
En ese directorio estará el fichero PruebaCS.snk.
Escribe lo siguiente (acuérdate de pulsar la tecla INTRO después de escribir eso):

sn -p PruebaCS.snk PruebaCS.publickey

Esto creará un fichero binario con la clave pública.

Ahora escribe lo siguiente:

sn -tp PruebaCS.publickey >PruebaCS.publickey.txt

Con esto lo que haces es exportar la clave pública a un fichero (si no usas el >PruebaCS.publickey.txt, te lo mostrará en la misma ventana).

Abre ese fichero con el bloc de notas (u otro editor de textos), y fíjate que el contenido será parecido al siguiente:

Microsoft (R) .NET Framework Strong Name Utility Version 2.0.50727.312
Copyright (c) Microsoft Corporation. All rights reserved.

Public key is
00240000048000009400000006020000002400005253413100040000010001001700669fa32c51
26d4e265b3983dcc0922ea414a0ef0e906356b48668e8f28694902943cd2a6fa35d673cfe0dcd5
6e8af08752dfee6e1b54f7afa666d26818e3f3291e9c8e392513581c7bedb7145b7c4152137602
f8d76de71ba802e7f72bacc6ba6bea471da2151bcac15907dac77292f1d9220d4f8bc489745366
abdca3c8

Public key token is 1766a08f664411c1

Lo que tienes que hacer es unir la ristra de números que hay bajo "Public key is" y copiarla.

Esa ristra de números es la que tienes que poner después del signo igual (donde están los tres puntos suspensivos) en:
<Assembly: InternalsVisibleTo("InternalsVisibleTo02_cs, PublicKey=...")>

Recuerda que ese atributo está en el proyecto InternalsVisibleTo01_vb.

 

Ahora compila todo el proyecto nuevamente y verás que puedes usar desde el proyecto de C# las clases y métodos Friend del proyecto de Visual Basic.

Nota:
Si estás usando las versiones Express de Visual Basic 2005 y Visual C# 2005, tendrás que compilar primero el proyecto de Visual Basic y asegurarte de que el proyecto de C# tiene una referencia al ensamblado de Visual Basic. Después de añadir (o actualizar) la referencia, puedes ejecutar el proyecto de C# y verás que funciona.

 

Usar un ensamblado amigo desde Visual Basic 9.0 (Orcas)

Como te he comentado antes, en Visual Basic 2005 NO se pueden usar ensamblados amigos, aunque sí crearlos.

Pero con Visual Basic 9.0 (el que se incluye en Visual Studio Orcas) si que puede usarlos.

Si tienes el Visual Studio Orcas (lo puedes bajar e instalar), abre el proyecto InternalsVisibleTo01_vb (te mostrará un aviso diciendo que lo tendrás que convertir, así que... lo conviertes...).

Añade un nuevo proyecto de tipo consola y dale el nombre InternalsVisibleTo02_vb.

En ese proyecto, tendrás que agregar un fichero de nombre seguro, (sigue los mismos pasos que te he explicado antes), además de averiguar la clave pública.

Para simplificar, puedes usar la misma clave que has creado en el proyecto de C# y usar esos mismos valores... pero si quieres crear uno nuevo... pues... ya sabes que tienes que seguir los pasos que te he indicado antes en Averiguar la clave pública de un fichero de claves.

Ahora añade una referencia al proyecto anterior "InternalsVisibleTo01_vb" de Visual Basic.

Por último, pega este código en el fichero Module1 que tendrás en ese proyecto de consola.

' En Visual Basic 2005 no se puede usar InternalsVisibleTo
' pero si en Visual Basic 9.0 (Visual Studio Orcas)

Imports InternalsVisibleTo01_vb

Module Module1
    Sub Main()

        Dim c1 As New Class1
        c1.Nombre = "elGuille"
        Console.WriteLine(c1.Nombre)
        Console.WriteLine(c1.Saludo())
        Console.WriteLine(c1.Saludo2())

        Dim c2 As New Class2
        Console.WriteLine(c2.Saludo())
        Console.WriteLine(c2.Saludo2())

        Console.ReadKey()
    End Sub
End Module

 

Si ejecutas el proyecto verás que te dará error.

No es que esté mal, sino que en el proyecto de la librería de clases (InternalsVisibleTo01_vb) debes decirle que ese ensamblado es amigo de este nuevo.

Por tanto, tendrás que añadir la siguiente línea al fichero del proyecto anterior:

<Assembly: InternalsVisibleTo("InternalsVisibleTo02_vb, PublicKey=...")> 

Y poner en los puntos suspensivos el número con la clave pública del fichero de claves que hayas usado para firmar el proyecto InternalsVisibleTo02_vb.

Nota:
En el ZIP con el código de ejemplo para Visual Studio Orcas he usado el mismo fichero de claves que el de C#.

Ahora vuelve a compilarlo todo (o simplemente pulsa F5) y verás que todo funciona bien.

 

Y esto es todo... espero que haya quedado bien claro y que te sea de utilidad.

 

Nos vemos.
Guillermo

 


Espacios de nombres usados en el código de este artículo:

System.Runtime.CompilerServices

 

 


Nota:
La mayoría del código de ejemplo, contienen más cosas de las indicadas en el título o link, por tanto te recomiendo que le eches un vistazo por si está lo que realmente andas buscando.

También quiero recordarte que en la mayoría de los casos, al menos en los links con fecha 15 de enero 2002 y posteriores en los que "el Guille" es el autor (yo), el mismo código se muestra tanto para Visual Basic como para C#, salvo casos muy concretos en los que se explican cosas específicas de cada lenguaje... o porque no he tenido tiempo de convertirlo, je, je.

Notas:
-El código mostrado en estas páginas es de libre uso, el único requisito para poder usarlo, es citar la procedencia del mismo.
-Para poder usar los tutoriales o los artículos, por ejemplo para publicarlos en otro sitio, tendrás que pedir autorización al autor antes de publicarlos (completo o en parte), y si es una colaboración, mándame copia de esa autorización a mi cuenta de correo: mensaje EN elguille.info.
Gracias.


 


Código de ejemplo (comprimido):

Código de ejemplo para Visual Studio Orcas: ensambladosAmigosOrcas.zip - 19.9 KB

(MD5 checksum: 4111E356F7BD0D26F82FF729967CD2FF)

 

Código de ejemplo para Visual Studio 2005: ensambladosAmigos2005.zip - 15.4 KB

(MD5 checksum: 98151E2598092912697C2A7DAAB2A50E)

 


 


La fecha/hora en el servidor es: 22/12/2024 17:09:23

La fecha actual GMT (UTC) es: 

©Guillermo 'guille' Som, 1996-2024