Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Duda en C# al trabajar con librerías

Iniciado por XÑA, 17 de Agosto de 2011, 05:46:08 PM

« anterior - próximo »

XÑA

Veamos, si yo tengo una librería matemática, por ejemplo, MathDX. Luego tengo otra igualita, llamada MathGL.

Entonces si tengo un proyecto y en el proyecto quiero usar una u otra en código, algo así como:

MathLibrary.Select(MathDX);

¿Como puedo indicarlo en C#? Pq en C, puedo crearme punteros y asociarlos a cada librería, pero en C# necesito tener la referencia en el proyecto, y por lo tanto, no se permite que se haga por código...

¿Alguien sabe si se puede hacer? ¿Vicente?

Vicente

#1
La manera mas tipica en .NET de hacer esas cosas es algo como (por ejemplo con un motor que soporte diferentes renderers):

- Tienes una libreria que define un renderer abstracto.
- Tienes X librerias que implementan cada renderer en concreto (DXRenderer, OpenGLRenderer,...).
- Utilizas algun mecanismo para cargar la libreria que quieras. El mas tipico es leer un fichero de configuracion y segun lo que leas cargas la DLL adecuada por reflexion. Si estas usando .NET 4.0 podrias usar MEF (http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.aspx) o cualquier otra libreria de inyeccion de dependencias (pero si es solo para unos cuantos componentes, mejor usar MEF que ya viene de serie con el Framework y a correr).

Edit: asi era en Jade 2 :p

XÑA

Eres la leche!!!!  :o

¿Y tienes algún ejemplo así básico, básico? :-\

Vicente

La idea es algo como:

Tu Renderer abstracto para trabajar necesita un objeto base para funcionar ( un Device abastracto). Asi que en la libreria tienes algo como

[Import]
public AbstractDevice Device { get; set; }

El Import es un atributo de MEF que le dice a esa libreria que busque alguna DLL que tenga un AbstractDevice y que rellene esa referencia con lo que encuentre al comenzar la ejecucion del programa.

Luego por ejemplo tienes en tu DXRenderer:

public class DXDevice : AbstractDevice { ... }

Y por algun lado tienes:

[Export]
public DXDevice Device { get { /* create the DXDevice here */ }

Y un par de chorradas mas que necesita MEF, y eso hace que cuando ejecutes, MEF mire otras DLLs del directorio (o del sistema, o por otros lados, es muy configurable), busque un Export para cada Import, y si lo encuentra obtenga la referencia que necesitas (y si no lo encuentra te peta y te da un error avisandote).

A ver si luego puedo subir un ejemplillo a algun lado.

Vicente

He subido un ejemplo de código aqui:

http://kartones.net/files/folders/csharp/entry51901.aspx

Es un fichero .zip con una solución con 4 proyectos:

- MEFExample: es una aplicación de consola, sería por ejemplo el juego.
- GraphicsCore: es el engine que utilizamos para programar nuestro juego. Como es un super engine permite usar DX y OGL.
- DxBackend: es una implementación de ciertas cosas del engine para DX.
- OglBackend: es una implementación de ciertas cosas del engine para OGL.

El código es totalmente de juguete (strings y poco más), solo es para explicar como se utiliza MEF.

La idea es que MEFExample pueda usar DX u OGL sin necesidad de tener las referencias en el Visual Studio y cosas así. Lo primero es hacer nuestro motor independiente de una libreria u otra. Para eso en GraphicsCore tiene una clase Renderer que es la que se utiliza para pintar, pero las operaciones específicas se esconden detrás de una interfaz IDevice que las implementaciones especificas  (DX, OGL) implementarán. Hasta aquí nada nuevo.

La gracia es como obtiene nuestro Renderer un IDevice para poder utilizarlo para pintar:


[Import]
public IDevice Device { get; set; }


Lo importante es el atributo Import, eso le dice a MEF que cuando la aplicación se ejecute busque por algún sitio un IDevice para asignarlo a esa propiedad.

Así que ahora tenemos que en algún sitio crear ese IDevice. Eso se hace en las librerias especificas de DX y OGL de la siguiente manera:


public static class DxExporter
{
    [Export]
    public static IDevice Device { get; private set; }

    static DxExporter()
    {
        Device = new DxDevice();
    }
}


Aquí tenemos una propiedad que tiene un atributo Export. MEF busca para cada Import su Export correspondiente para unirlos. Para asegurarnos que en esa propiedad hay realmente algo y no es null, pues en el constructor estático inicializamos la propiedad.

Ahora, solo nos queda en la aplicación principal decirle a MEF que resuelva los Imports, esto se hace de la siguiente manera.


var catalog = new DirectoryCatalog(@"..\..\..\Libraries");
var container = new CompositionContainer(catalog);

Renderer renderer = new Renderer();
container.SatisfyImportsOnce(renderer);


Lo primero es decirle a MEF donde puede buscar Exports, que eso se hace con un Catalog. En este caso le hemos dicho que busque en un directorio llamado Libraries. Una vez que MEF sabe donde buscar, creamos el Renderer (que tenía el Import del IDevice), y le decimos a MEF que una el Import con algun Export que esté en alguna DLL en la carpeta Libraries (eso es lo que hace la linea SatisfyImportsOnce).

Si ejecutamos la aplicacion tal y como viene, dara un error porque la carpeta Libraries está vacia. Pero si copiamos la dll DxBackend.dll en esa carpeta, entonces la aplicación utilizará el Device de DX, y si copiamos la dll OglBackend.dll entonces utilizará OGL. Si copiamos las dos dará un error porque no le hemos dicho como resolver ese caso (MEF se puede complicar mucho mucho, esto es solo un ejemplo básico).

Ale, espero que ayude :)

XÑA







Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.