Crear componentes de .NET con PerlNET 


F. Javier García Castellano
Web: http://geneura.ugr.es/~javi, Mail: fjgc@decsai.ugr.es
Usar objetos de .NETInicioReferencia de PerlNET

(C) GeNeura Team
Web: http://geneura.ugr.es, Mail: tutti@geneura.ugr.es

1.- Componentes en PerlNET

Con PerlNET es muy fácil enmascarar un módulo que existe en Perl, para crear un componente de .NET, basta con crear un interfaz adicional al módulo con una especificación para el mismo.

Para ver esto, utilizaremos un ejemplo, para ello usaremos el módulo WWW::Babelfish del CPAN, el cual sirve para hacer traducciones usando el sitio http://babelfish.altavista.com.

como se puede ver en la documentación del módulo WWW::Babelfish tiene tres métodos: el constructor, el método translate (que toma 6 cadenas como parámetros y devuelve el texto traducido) y el método languages que devuelve un array con los lengujaes que soporta el módulo.

Para hacer que este módulo esté disponible en PerlNET, se haría como sigue:

Módulo WWW::Babelfish como componente de .NET:

package WWW::Babelfish;

=for interface
    [interface: pure]
    static Babelfish Babelfish();
    str translate(str key1, str value1,
                  str key2, str value2,
                  str key3, str value3);
    wantarray! str[] languages();
=cut

require WWW::Babelfish;

Con el anterior trozo de código, hacemos que el módulo WWW::Babelfish esté disponible para cualquier lenguaje que pertenezca a .NET. Lo primero que hemos hecho ha sido darle un nombre al nuevo componente (package WWW::Babelfish;). Posteriormente y usando la sintaxis de la documentación de módulo se ha añadido la interfaz de acceso al módulo desde .NET. Y finalmente se ha incluido el módulo en cuestion (require WWW::Babelfish;).

Dentro de la interfaz se ha añadido el pseudo atributo interface con valor igual a pure ([interface: pure]), con esto estamos diciendo que estamos creando el interfaz para un tipo/objeto puro de Perl (que está construido sólo con elementos de Perl y nada de .NET). Luego distinguimos las definición de tres métodos, el constructor, el método translate y el método languages.

Como vemos en la definición del constructor se utiliza el nombre de la clase y no new (ya hemos dicho que en .NET se utiliza el nombre de la clase para el constructor y en PerlNET se utiliza new) y se define como un método static, porque en .NET todos los constructores son estáticos.

En la definición del método translate vemos que acepta seis cadenas (str) como parámetros y devuelve una cadena. Observemos que al estar construyendo el interfaz de acceso al módulo desde .NET, tenemos que trabajar con los tipos de datos de .NET.

En el método languages vemos que no acepta ningún parámetro pero que devuelve un array de cadenas. Cuando un método de Perl devuelva un array tenemos que anteponer la palabra reservada (wantarray!) para que .NET sepa que está en un contexto de listas.

Ya hemos hecho que el módulo esté disponible para cualquier lenguaje de .NET. Por ejemplo, vamos a usar dicho módulo, desde un programa de C#

Programa de c# que utiliza el módulo WWW::Babelfish:

using System;

class main
{
    public static void Main(string[] args)
    {
        string text = "The quick brown fox jumps over the lazy dog";
        string[] lang = { "French", "German", "Spanish", "Italian" };

        Console.WriteLine("{0}: {1}", "English", text);
        using (WWW.Babelfish fish = new WWW.Babelfish()) {
            foreach (string dest in lang) {
                string trans = fish.translate("source",       "English",
                                              "destination",  dest,
                                              "text",         text);
                Console.WriteLine("{0}: {1}", dest, trans);
            }
            Console.WriteLine();

            foreach (string str in fish.languages())
                Console.WriteLine("Language: {0}", str);
        }
    }
}

Como vemos los métodos utilizado son los definidos en el interfaz, es decir, el constructor no se llama new (que es como realmente se llama en Perl) sino con el nombre de la clase tal y como se hace con todos los contructores de PerlNET y como hemos definido en el interfaz.

Para poder ejecutar los anteriores ejemplos, primero hay que tener el módulo WWW::Babelfish instalado en el sistema. Y compilar el componente y el ejemplo, com sigue:

plc -target library Babelfish.pl
csc prueba.cs -r:Babelfish.dll

Veamos como se definiría el interfaz del módulo Persona.pm (visto en el Tutorial de Perl: Objetos) para su posterior uso en .NET:

Módulo Persona como componente de .NET:

package Persona;

=for interface
    [interface: pure]

    static Persona Persona();

    str nombre();

    str nombre(str nuevo);

    int nombre();

    int nombre(int nueva);

    int nombre();

=cut

require Persona;

Aqui vemos como se hace uso de la sobrecarga de métodos de Perl. En Perl no hay sobrecarga de métodos como tal y se tiene que hacer en función de de los argumentos que se le pasan al método (array @_). En la clase Persona, el que se modificase o sólamente se viese una propiedad dependía de que se pasase o no un parámetro con el nuevo valor. Esto es lo que se ha reflejado en el interfaz.

2. Ejercicios

Ejercicio: Usa la clase Alumno.pm (realizada en el tutorial de Perl) desde un programa en C# o VB.NET o VC++.NET