Jul 30 2008

Ordenar una lista con expresiones Lambda (múltiples criterios) VB.Net {

Tag: VB.Net

Este post se trata de como ordenar una lista de objetos de acuerdo a varios criterios utilizando una sola expresión lambda. El ejemplo está hecho utilizando el .net framework 3.5 (Visual Studio 2008).

Tenemos una lista de objetos con la siguiente estructura:

Public Class Elemento
    Public Sub New(ByVal mNum As Integer, ByVal mPrioridad As Prioridades, ByVal mValor As Integer)
        Numero = mNum
        Prioridad = mPrioridad
        Valor = mValor
    End Sub
 
    Public Enum Prioridades
        Alta = 0
        Media = 1
        Baja = 2
    End Enum
 
    Public Numero As Integer
    Public Prioridad As Priorities
    Public Valor As Integer
End Class

Para este ejemplo utilizaremos un objeto List(Of Elemento) que llenaremos con valores aleatorios y necesitaremos ordenarla de acuerdo a los siguientes criterios:

  • Primero: Numero en orden ascendente
  • Segundo: Prioridad de mayor a menor
  • Tercero: Valor en orden ascendente

Supongamos que nuestra lista se completó con los siguientes elementos:

Num Prioridad Valor
4 Baja 16
1 Alta 26
3 Media 87
4 Media 10
2 Baja 3
5 Alta 4
4 Media 134
2 Baja 342

Nuestro resultado debe ser el siguiente:

Num Prioridad Valor
1 Alta 26
2 Baja 3
2 Baja 342
3 Media 87
4 Media 10
4 Media 134
4 Baja 16
5 Alta 4

Por lo tanto nuestra expresión lambda será la siguiente:

Public Sub LambdaSort(ByVal lista As List(Of Element))
        lista.Sort(Function(x, y) _
                x.Numero.CompareTo(y.Numero) Or _
                (x.Numero.Equals(y.Numero) And x.Prioridad.CompareTo(y.Prioridad)) Or _
                (x.Numero.Equals(y.Numero) And x.Prioridad.Equals(y.Prioridad) And x.Valor.CompareTo(y.Valor)))
End Sub

La expresión está hecha en una sola línea que fue separada para comodidad en la lectura, por lo que iremos viendo linea a linea, en la primera declaramos la expresión lambda que va a ordenar la lista:

lista.sort(Function(x,y)

luego vamos ennumerando nuestras condiciones:

x.Numero.CompareTo(y.Numero) Comparamos el valor de x.Numero con el de y.Numero, esta comparación nos devuelve el orden ascendente o sea x < y.
(x.Numero.Equals(y.Numero) And x.Prioridad.CompareTo(y.Prioridad)) Si x.Numero = y.Numero comparamos la Prioridad de ambos al igual que lo hicimos en el punto anterior con Numero.
(x.Numero.Equals(y.Numero) And x.Prioridad.Equals(y.Prioridad) And x.Valor.CompareTo(y.Valor)) Si x.Numero = y.Numero y también x.Priridad = y.Pririodad comparamos el Valor.

Separamos cada uno de los criterios de ordenación con OR para que se aplique uno u otro y listo.

Sin duda una forma simple y rápida de ordenar una lista.

}


Jul 28 2008

Como reemplazar texto de un documento usando JavaScript y expresiones regulares {

Tag: JavaScript, RegEx

Seguramente todos han visto alguna vez una página que resalta las palabras clave nuestra búsqueda, y eso es lo que podemos lograr con estas 2 funciones de JavaScript y las siempre útiles expresiones regulares, por supuesto se puede hacer todo en una misma función, pero la idea es poder reusar el código.

La primera función se encargará de extraer el valor de un parámetro de nuestra URL usando expresiones regulares y sólo devolverá el valor. Se tuvo en cuenta que un parámetro de URL siempre estará precedido por uno de estos signos: ? ó & y que el valor del mismo se encontrará precedido del signo = y podrá ser sucedido por uno de los siguientes: & ó #.
A la hora de devolver el valor del parámetro seleccionado se utiliza una nueva expresión regular para reemplazar los signos + ó %20 por espacios en blanco, y en caso de que no se encuentre el parámetro devuelve un string vacío.

function leerParametros() {
	var parametro = 's'; //nombre del parámetro con las palabras de la búsqueda
	var regex = new RegExp('(\\?|&)('+ parametro + '=)([^&#]*)', 'i'); //regex para extraer el valor del parámetro
	var resultado = regex.exec(window.location.href); //ejecuta la regex sobre nuestra URL actual
 
	if(resultado != null) {
		replaceRegex = new RegExp('\\+|%20', 'g'); //regex para reemplazar signos por espacios
		return resultado[3].replace(replaceRegex, ' '); // devuelve la 3 coincidencia de la regex con el reemplazo para los espacios
	} else {
		return ""; //si la regex no encuentra el parámetro se devuelve un string vacío
	}
}

Luego utilizamos la función que realmente va a resaltar nuestras palabras clave, lo que haremos será obtener el valor del parámetro con la función anterior y mediante una expresión regular rodearemos cada instancia del texto con un tag <span> que tendrá un atributo style para darle la apariencia mediante css.

En esta expresión regular utilizamos paréntesis para poder capturar la coincidencia de texto como $1, ya que sino la estaríamos reemplazando por el texto buscado y es muy posible que no se respete la capitalización del texto original.

function resaltar() {
	var textoOriginal = leerParametros(); //obtiene el valor del parámetro
	var textoNuevo = "<span style=\"background-color: #ff0; font-weight: bold;\">$1</span>"; //define el texto a insertar por cada coincidencia de la regex
	var regex = new RegExp('('+textoOriginal+')', 'ig'); regex con modificadores ig, o sea no sensible a mayúsculas y minúsculas (i) y reemplazar todas las existencias (g)
	document.body.innerHTML = document.body.innerHTML.replace(regex, textoNuevo); //reemplazo sobre el html del body
}

Por último sólo resta hacer el llamado en el documento de destino, para lo cual lo ideal sería asignar la función resaltar() al evento onload del documento, pero eso no me funcionó, por lo que lo inserté al final del mismo:

		<script type="text/javascript">
				resaltar();
		</script>
	</body>
</html>

Sigue este enlace para ver el ejemplo funcionando.

}


Jul 28 2008

Como hacer un plugin para Wordpress {

Tag: PHP, Wordpress

Luego de escribir mi primer plugin, voy a explicar a grandes rasgos lo que se necesita para escribir un plugin, éste está compuesto de 2 archivos, uno con la funcionalidad del plugin y otro con la página de opciones para el panel de administración de wordpress.

Lo primero que haremos será escribir el encabezado para el plugin, ésto es lo que permitirá que Wordpress reconozca el plugin.

/* 
Plugin Name: Category 2 Post 
Plugin URI: http://nuevosprogramadores.com/category2post/ 
Description: Allows to include posts from one selected category 2 your post or page body. 
Version: 0.1 Author: Pablo Rodríguez Author URI: http://nuevosprogramadores.com 
*/ 
/*  Copyright 2008  Pablo Rodríguez  (email : prodriguez@nuevosprogramadores.com)      
This program is free software; you can redistribute it and/or modify     
it under the terms of the GNU General Public License as published by     
the Free Software Foundation; either version 2 of the License, or     
(at your option) any later version.      
This program is distributed in the hope that it will be useful,     
but WITHOUT ANY WARRANTY; without even the implied warranty of     
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     
GNU General Public License for more details.      
 
You should have received a copy of the GNU General Public License     
along with this program; if not, write to the Free Software     
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/

Como se puede apreciar, el encabezado está compuesto de 2 comentarios, sólo el primero es obligatorio, el segundo especifica que el plugin es publicado bajo licencia GPL.

Luego escribiremos la funcionalidad del plugin, en nuestro caso es una función que recorre los posts de una determinada categoría, arma un html con el contenido y por último reemplaza el comentario <!--category2post--> por el html con los posts que encontró anteriormente.

function category2post($c2p_content) { 
	$c2p_IDCategory = stripslashes(get_option('c2p_IDCategory')); 
	$c2p_NumberOfPosts = stripslashes(get_option('c2p_NumberOfPosts')); 
	$c2p_ShowAllContent = stripslashes(get_option('c2p_ShowAllContent')); 
	$c2p_result = ""; $c2p_posts = array(); 
 
	switch($c2p_NumberOfPosts) { 
		case 0: 
			c2p_posts = get_posts("category=$c2p_IDCategory"); 
			break; 
		default: 
			$c2p_posts = get_posts("numberposts=$c2p_NumberOfPosts&amp;category=$c2p_IDCategory"); 
			break; 
		} 
		if(sizeof($c2p_posts)) { 
			foreach($c2p_posts as $c2p_post) { 
			$c2p_result .= "<h3><a href="\">guid."\" id=\"".$c2p_post-&gt;ID."\"&gt;".$c2p_post-&gt;post_title."</a></h3>\n";
			if($c2p_ShowAllContent == '0') { 
				$c2p_result .= $c2p_post-&gt;post_excerpt."\n"; 
			} else { 
				$c2p_result .= $c2p_post-&gt;post_content."\n"; 
			} 
		} 
	} 
	return preg_replace('<!-- category2post -->|', $c2p_result, $c2p_content); 
}

Es muy importante buscar que los nombres de las funciones para no tener problemas con otros plugins y si las hubiese, hay que aplicar el mismo criterio con las variables. En mi caso utilicé el mismo prefijo para todo.

Como este plugin requiere de configuración, escribiremos también una función que agregue la página al panel de Wordpress.

function c2p_add_option_page() { 
	add_options_page('Opciones', 'Category2Post', 'manage_options', 'category2post/options-c2p.php'); 
}

Y por último haremos que todo esto funcione:

add_action('admin_head', 'c2p_add_option_page'); add_filter('the_content', 'category2post');

La primera línea asigna nuestra función c2p_add_option_page a la acción admin_head de Wordpress, mientras que la segunda indica que nuestra función category2post se debe ejecutar con el filtro the_content.

Por suerte Wordpress cuenta con una buena Referencia de Funciones, que nos sirve como guía para nuestras creaciones, además contamos con otros plugins que podemos utilizar como referencia para ver el código.

Hasta aquí las funciones que utilizamos son: get_option que nos permite obtener el valor de una opción desde la base de datos, get_posts para obtener los posts que cumplan con cierto criterio, en nuestro caso buscamos los que pertenezcan a una categoría y de ser necesario, que sólo devuelva x cantidad de posts, add_options_page para agregar nuestra página de opciones al panel de administración de Wordpress y por último add_action y add_filter.

}


Jul 26 2008

Plugin para Wordpress - Category2Post - v0.1 {

Después de mucho tiempo diciendo “algún día voy a hacer un plugin para Wordpress”, finalmente llegó el día, desde hoy se encuentra funcionando en Nuevos Programadores el plugin Category2Post que se encarga de recopilar las entradas publicadas bajo la categoría Mini Tips y mostrarlos en la página del mismo nombre.

El plugin está totalmente escrito en php y utiliza funciones de la muy documentada API de Wordpress para seleccionar los posts y mostrarlos. Si hay algún curioso que desee ver como funcionan los plugins de Wordpress, éste es bastante simple, lo suficiente como para entender la lógica para escribir un plugin e incluir una página para la configuración de opciones.

En un próximo post voy a explicar lo básico de la experiencia que fue escribir mi primer plugin para wordpress, mientras tanto si alguien lo prueba y encuentra algún bug o se le ocurre que se podría agregar una nueva funcionalidad, puede dejar un comentario o comunicarse conmigo a través del formulario de contacto del blog.

Descargar Category2Post

}


Jul 25 2008

Obtener información de la pantalla con C# {

Tag: C#, Mini Tips

Más de una vez se puede dar una situación en la que necesitamos ubicar un form en determinada área de la pantalla, o redimensionarlo de acuerdo al tamaño de ésta, para eso necesitamos saber al menos el ancho y alto de nuestra pantalla, o sea la resolución de pantalla.

La función a continuación nos devuelve un String que contiene información útil acerca de la pantalla donde se está ejecutando la aplicación. Tomando esta función como ejemplo, se puede por ejemplo ubicar un form en la esquina inferior derecha de nuestra pantalla.

        public String InfoPantalla(System.Windows.Forms.Control c)
        {
            // \r\n es salto de línea y \t es tabulador
            return String.Format("Es Primario: \t{0}\r\nAncho: \t{1}\r\nAlto: \t{2}\r\nAncho útil: \t{3}\r\nAlto útil: \t{4}",
                System.Windows.Forms.Screen.FromControl(c).Primary, // Devuelve True si se trata del monitor principal del quipo
                System.Windows.Forms.Screen.FromControl(c).Bounds.Width, // Devuelve el ancho total de la pantalla
                System.Windows.Forms.Screen.FromControl(c).Bounds.Height, // Devuelve el alto total de la pantalla
                System.Windows.Forms.Screen.FromControl(c).WorkingArea.Width, // Devuelve el ancho útil de la pantalla, sin contar docks y taskbars
                System.Windows.Forms.Screen.FromControl(c).WorkingArea.Height); // Devuelve el alto útil de la pantalla, sin contar docks y taskbars
        }
    }

La función recibe un objeto Control porque está pensaga para ser implementada en una clase, pero si la misma se implementa en un WindowsForm, o por qué no, un UserControl, Screen.FromControl() puede recibir directamente this como parámetro.

}


Jul 25 2008

Como obtener el directorio de ejecución con VB.Net {

Tag: Mini Tips, VB.Net

Hay varias formas de llegar al mismo resultado, la idea es obtener la ruta del directorio donde se está ejecutando nuestra aplicación, a continuación dejo 3 funciones que nos llevan al mismo resultado.

Para probarlas, basta con crear una nueva aplicación de consola, agregar las 3 funciones y llamarlas:

   Sub Main()
        Console.WriteLine(ObtenerDirectorio_1())
        Console.WriteLine(obtenerDirectorio_2())
        Console.WriteLine(obtenerDirectorio_3())
        Console.Read()
    End Sub

    Function ObtenerDirectorio_1() As String
        Return System.Threading.Thread.GetDomain().BaseDirectory()
    End Function

    Function ObtenerDirectorio_2() As String
        Return Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\") + 1)
    End Function

    Function ObtenerDirectorio_3() As String
        Return System.Reflection.Assembly.GetExecutingAssembly().Location.Substring(0, Application.ExecutablePath.LastIndexOf("\") + 1)
    End Function

}


Jul 22 2008

Manejo de hilos en C# (parte 1) + delegates + invoke {

Tag: C#

En el artículo que explica la implementación del patrón Singleton en C# utilizamos un método que inicializa 42 hilos los cuales modifican un atributo del objeto Singleton. Además de eso, cuando se lanza el evento que “avisa” de la modificación del atributo, se muestra el valor en una label del form, por lo cual deberemos usar delegados para evitar un problema de CrossThreadException.

Primero veamos el código que crea los threads:

private void button2_Click(object sender, EventArgs e)
        {
            System.Threading.ThreadStart ts = new System.Threading.ThreadStart(sumarRandomico);
 
            Int16 i;
            for (i = 0; i <= 42; i++)
            { 
                System.Threading.Thread t = new System.Threading.Thread(ts);
                t.IsBackground = true;
                t.Name = String.Format("Thread_{0}", i.ToString());
                t.Start();
                System.Diagnostics.Trace.WriteLine(String.Format("Thread {0} >>> Contador: {1} <<<", t.Name, objetoSingleton.Instancia.Contador.ToString()));
            }
        }

En la primera linea creamos el ThreadStart, que es el que indica el método que se ejecutará en el thread, luego dentro del bucle for creamos el objeto thread, seteamos que se ejecute en background, le seteamos un nombre y luego iniciamos la ejecución del hilo. Hasta ahí no hay misterio, simplemente instanciamos e iniciamos varios hilos, en caso de que el método que se ejecutará en el nuevo hilo requiera parámetros, utilizaremos un ParameterizedThreadStart que veremos en la segunda parte de este artículo.

Ahora veamos cómo mostrar en pantalla el valor evitando las CrossThreadException, las mismas suceden cuando se intenta acceder a un objeto de un hilo, (la interfaz en este caso), desde otro hilo.
Cuando se intenta acceder a un control desde otro hilo, la propiedad InvokeRequired toma el valor true, por lo que consultando el valor de esta propiedad sabremos si podemos acceder directamente al control o no.

void Instancia_CambioContador(long nuevoValor)
        {
            if (!this.label2.InvokeRequired)
            {
                CambiarValorLabel(nuevoValor.ToString());
            }
            else
            {
                CambiarValorDelegate del = new CambiarValorDelegate(CambiarValorLabel);
                this.label2.Invoke(del,nuevoValor.ToString());
            }
        }
 
        private delegate void CambiarValorDelegate(String nuevoValor);
        private void CambiarValorLabel(String nuevoValor)
        {
            this.label2.Text = nuevoValor;
        }

Como vemos, si InvokeRequired es false, llamamos directamente al método que modifica el Text de nuestra label, de lo contrario necesitaremos crear un delegate para ese método y utilizarlo con el método Invoke del control.
Un delegate es, a grandes rasgos, un puntero, lo cual en este caso evita la CrossThreadException porque accede directamente a la dirección de memoria del método que llamaremos. Para utilizar un delegate, tenemos que definirlo primero y éste debe tener la misma firma que el método que llamará.

Al momento de utilizarlo, instanciamos nuestro delegate y utilizamos el método Invoke de nuestra label:

CambiarValorDelegate del = new CambiarValorDelegate(CambiarValorLabel);
this.label2.Invoke(del,nuevoValor.ToString());

}


Jul 22 2008

Implementación del patrón Singleton en C# {

Tag: C#, Patrones, Singleton

El patrón Singleton se utiliza cuando es necesario tener una única instancia de una clase para toda la aplicación, ésto se logra otorgando la responsabilidad de crear la instancia a la misma clase. En nuestro ejemplo vemos que el constructor es privado y la propiedad Instancia se encarga de instanciar el objeto, (si éste no fue instanciado antes), y devolver la única instancia.

El código de nuestra clase es el siguiente:

public class objetoSingleton 
{ 
	private DateTime _creacion; 
	private Int64 _contador = 0; 
 
	public event onCambioContador CambioContador; 
	public delegate void onCambioContador(Int64 nuevoValor); 
 
#region Singleton 
	private static Object lockObject = new Object();
	private static objetoSingleton _instancia; 
 
	private objetoSingleton() { 
		this._creacion = DateTime.Now; 
	} 
 
	public static objetoSingleton Instancia 
	{ 
		get 
		{ 
			lock (lockObject) 
			{ 
				if (_instancia == null) 
				{ 
					_instancia = new objetoSingleton(); 
				} 
				return _instancia; 
			} 
		} 
	} 
#endregion 
 
	public DateTime FechaHoraCreacion 
	{ 
		get { return _creacion; } 
	} 
 
	public void SumarContador(Int64 valor) 
	{ 
		_contador += valor; 
		CambioContador(_contador); 
	} 
 
	public Int64 Contador 
	{ 
		get { return _contador; } 
	} 
}

Como se puede ver en el código, al cambiar el valor del contador se lanza un evento, que luego capturaremos para mostrar el valor del contador.
Para probar nuestro Singleton, vamos a usar un form, que podrá acceder directamente al objeto para sumar 1 al contador, podrá además crear 42 hilos que sumarán números aleatorios al contador y también podrá crear instancias de si mismo.

Al final del artículo está el enlace para descargar el proyecto hecho en Visual Studio 2005, además en este post estudiaremos el manejo de hilos, (threads), en C# utilizado en el form.

Descargar el ejemplo de Patrón Singleton en C# (21.22 KB)

}


Jul 22 2008

Aplicación con plugins en VB.Net {

Tag: VB.Net

Este ejemplo muestra una forma sencilla de crear aplicaciones cuya funcionalidad se puede extender con el uso de plugins o agregados.
En este caso, como lo que importa es mostrar como se hace la carga mediante herramientas de Reflection, nuestros plugins son sólo forms con una funcionalidad muy simple, un web browser y un reloj… queda en la imaginación de cada uno crear algún nuevo plugin.

Para la carga de los plugins, o sea buscar los archivos y cargar los menús correspondientes utilizaremos un nuevo thread, pero como no es el propósito de este post mostrar el manejo de threads, utilizaremos un Background Worker que automatiza el proceso.

    Private Sub bgwCargaPlugins_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwCargaPlugins.DoWork
        Dim DirectorioPlugins As String = String.Format("{0}{1}", Threading.Thread.GetDomain().BaseDirectory, "plugins")
        If Directory.Exists(DirectorioPlugins) Then
            For Each _dir As String In Directory.GetDirectories(DirectorioPlugins)
                Try
                    Dim aux As System.Collections.Generic.KeyValuePair(Of String, String) = PluginLoader.CargarPluginDesdeDirectorio(_dir)
                    _pluginsEncontrados.Add(aux.Key, aux.Value)
                Catch ex As Exception
                    Trace.WriteLine(ex.ToString())
                End Try
            Next
        Else
            Trace.WriteLine("El directorio de plugins no existe.")
        End If
    End Sub
 
    Private Sub bgwCargaPlugins_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgwCargaPlugins.RunWorkerCompleted
        If _pluginsEncontrados.Count > 0 Then
            mostrarMenuDePlugins()
        End If
    End Sub

Lo primero que hacemos es chequear que el directorio de plugins exista, en este caso es un directorio hard-coded llamado plugins que se ubica en el directorio de instalación, pero en una aplicación real deberíamos podríamos hacer que esa ruta sea configurable.
Luego recorreremos los subdirectorios y pasaremos la ruta de cada uno a nuestra clase PluginLoader para guardar el resultado en un objeto del tipo Dictionary(Of String, String), que a grandes rasgos es una colección ordenada que guarda un valor asociado a una determinada clave; en este caso, la clave será el nombre del tipo a cargar, o sea el form del plugin y el valor será la ruta a la dll que contiene el plugin.

Una vez que el background worker ha finalizado su ejecución, llamamos a un método que lo que hará es recorrer nuestro Dictionary cargado de plugins y agregar un item al menú plugins y agregarle un handler genérico para el evento click a cade item que agregue.

    ' Método que carga los items en el menú
    Public Sub mostrarMenuDePlugins()
        For Each p As System.Collections.Generic.KeyValuePair(Of String, String) In _pluginsEncontrados
            Dim aux As System.Windows.Forms.ToolStripMenuItem = Me.PluginsToolStripMenuItem.DropDownItems.Add(p.Key)
            AddHandler aux.Click, AddressOf PluginMenuClick
        Next
        Me.PluginsToolStripMenuItem.Enabled = True
    End Sub
 
    ' handler para el evento click de cada item del menú plugins
    Public Sub PluginMenuClick(ByVal sender As Object, ByVal e As System.EventArgs)
        Try
            Dim plugin As Form = PluginLoader.InstanciarPlugin(_pluginsEncontrados.Item(sender.ToString()), sender.ToString())
            plugin.MdiParent = Me
            plugin.Show()
        Catch ex As Exception
 
        End Try
    End Sub

Lo que haremos en el click de cada item del menú plugins será pedirle a nuestra clase PluginLoader que nos instancie el plugin para luego mostrarlo como MDI Child.

Ahora sólo nos resta ver el código de la clase PluginLoader:

Imports System.IO
 
Public Class PluginLoader
    Public Shared Function CargarPluginDesdeDirectorio(ByVal Directorio As String) As System.Collections.Generic.KeyValuePair(Of String, String)
        Dim aux As System.Collections.Generic.KeyValuePair(Of String, String) = Nothing
 
        'Busco solo los archivos .dll en el directorio especificado
        Dim archivos() As String = Directory.GetFiles(Directorio, "*.dll")
        If archivos.Length > 0 Then
            For Each dll As String In archivos
                Try
                    Dim assembly As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom(dll)
                    'Recorro los tipos que se encuentran en la dll cargada
                    For Each t As Type In assembly.GetTypes()
                        Try
                            'cargo solo los que son derivados de Form
                            If t.BaseType Is GetType(Form) Then
                                aux = New System.Collections.Generic.KeyValuePair(Of String, String)(t.Name, assembly.Location)
                            End If
                        Catch ex As Exception
                            Trace.WriteLine(ex.ToString())
                        End Try
                    Next
                Catch ex As Exception
                    Trace.WriteLine(ex.ToString())
                End Try
            Next
        End If
        Return aux
    End Function
 
    Public Shared Function InstanciarPlugin(ByVal RutaDll As String, ByVal PluginName As String, Optional ByVal ExtraData As Object = Nothing) As Form
        Dim TipoPlugin As Type
        Dim frm As Form
 
        Dim PluginAssembly As System.Reflection.[Assembly] = System.Reflection.[Assembly].LoadFrom(RutaDll)
        TipoPlugin = PluginAssembly.GetType(PluginName, False, True)
 
        If Not TipoPlugin Is Nothing Then
            Dim Instancia As Object
            'ExtraData se puede utilizar para pasar argumentos al constructor
            If ExtraData Is Nothing Then
                Instancia = Activator.CreateInstance(TipoPlugin)
            Else
                Dim arg() As Object = {ExtraData}
                Instancia = Activator.CreateInstance(TipoPlugin, arg)
            End If
 
            frm = CType(Instancia, Form)
        Else
            'En caso de error devuelvo un form cualquiera con el texto de error
            frm = New Form()
            frm.Text = "Error cargando el plugin"
        End If
 
        Return frm
    End Function
End Class

El código de esta clase no es muy complejo y con los comentarios se puede entender lo más relevante de la misma, al final del artículo está el enlace para descargar la solución, que está hecha con Visual Studio 2005.

Con respecto a los plugins, son proyectos de tipo Class Library, los mismos tienen referencia a System.Windows.Forms y el proyecto de la aplicación principal no tiene ninguna referencia a éstos, de manera que el proyecto no tiene por qué estar incluido en la misma solución.

Descargar el código fuente de la aplicación con plugins en VB.Net (124.71 KB)

}


Jul 21 2008

Conectar a MySQL usando PHP {

Tag: MySQL, PHP

PHP es seguramente el lenguaje más usado para el desarrollo de aplicaciones web, y en la mayoría de las ocasiones es utilizado junto al motor de base de datos MySQL.

En este artículo crearemos una clase que se encargará de establecer una conexión con MySQL, insertar, modificar, eliminar y obtener registros.

A grandes rasgos, la clase se compone de un constructor, un destructor y los métodos que trabajan, en este caso, sobre una misma tabla. El ejemplo es muy simple, pero para empezar a trabajar con php y MySQL es suficiente.

Primero veamos la clase:


<?php
class socios_DAL {
	var $conn;
	var $db;
	var $ultimoComando;
 
	function __construct($dbName, $server, $user, $passwd) {
		if($dbName !== "" && $server !== "" && $user !== "" && $passwd !== "") {
			$this->conn = mysql_connect($server, $user, $passwd) or die("Error al intentar establecer la conexión.");
			if(isset($this->conn)) {
				$db = mysql_select_db($dbName, $this->conn) or die("Error al intentar seleccionar la base de datos.");
				$this->ultimoComando = array();
			}
		}
	}
 
	function __destruct() {
		if(isset($this->conn)) {
			mysql_close($this->conn);
		}
	}
 
	function obtenerUltimoComando() {
		return $this->ultimoComando;
	}
 
	function insertarSocio($num, $nombre, $apellido, $domicilio) {
		if($num !== "" && $nombre !== "" && $apellido !== "" & $domicilio !== "") {
			$sql = "INSERT INTO `tblSocios` (`num`, `nombre`, `apellido`, `domicilio`) VALUES ('$num', '$nombre', '$apellido', '$domicilio')";
			if(mysql_query($sql, $this->conn)) {
				$this->ultimoComando = array('comando' => $sql, 'resultado' => 'ok');
				return true;
			} else {
				if(mysql_errno() || mysql_error()) {
					$this->ultimoComando = array('comando' => $sql, 'resultado' => "Error: ".mysql_errno().": ".mysql_error());
				} else {
					$this->ultimoComando = array('comando' => $sql, 'resultado' => 'error');
				}
				return false;
			}
		}
	}
 
	function eliminarSocio($num) {
		if($num !== "") {
			$sql = "DELETE FROM `tblSocios` WHERE `num` = '$num' LIMIT 1";
			if(mysql_query($sql, $this->conn)) {
				$this->ultimoComando = array('comando' => $sql, 'resultado' => 'ok');
				return true;
			} else {
				if(mysql_errno() || mysql_error()) {
					$this->ultimoComando = array('comando' => $sql, 'resultado' => "Error: ".mysql_errno().": ".mysql_error());
				} else {
					$this->ultimoComando = array('comando' => $sql, 'resultado' => 'error');
				}
				return false;
			}
		}
	}
 
	function modificarSocio($num, $nombre, $apellido, $domicilio) {
		if($num !== "" && $nombre !== "" && $apellido !== "" & $domicilio !== "") {
			$sql = "UPDATE `tblSocios` SET `nombre` = '$nombre', `apellido` = '$apellido', `domicilio` = '$domicilio' WHERE `num` = '$num' LIMIT 1";
			if(mysql_query($sql, $this->conn)) {
				$this->ultimoComando = array('comando' => $sql, 'resultado' => 'ok');
				return true;
			} else {
				if(mysql_errno() || mysql_error()) {
					$this->ultimoComando = array('comando' => $sql, 'resultado' => "Error: ".mysql_errno().": ".mysql_error());
				} else {
					$this->ultimoComando = array('comando' => $sql, 'resultado' => 'error');
				}
				return false;
			}
		}
	}
 
	function obtenerSocios() {
		$resultado = array();
		$sql = "SELECT * FROM `tblSocios` ORDER BY `apellido`, `nombre`";
		if($socios = mysql_query($sql, $this->conn)) {
			$indice = 0;
			while($s = mysql_fetch_array($socios)) {
				$resultado[$indice] = $s;
				$idice++;
			}
			mysql_free_result($socios);
			$ultimoComando = array('comando' => $sql, 'resultado' => 'ok');
		} else {
			if(mysql_errno() || mysql_error()) {
				$this->ultimoComando = array('comando' => $sql, 'resultado' => "Error: ".mysql_errno().": ".mysql_error());
			} else {
				$this->ultimoComando = array('comando' => $sql, 'resultado' => 'error');
			}
		}
		return $resultado;
	}
 
	function obtenerSocio($num) {
		if($num !== "") {
			$sql = "SELECT * FROM `tblSocios` WHERE `num` = '$num' LIMIT 1";
			if($socio = mysql_query($sql, $this->conn)) {
				$ultimoComando = array('comando' => $sql, 'resultado' => 'ok');
 
				return mysql_fetch_array($socio);
			} else {
				if(mysql_errno() || mysql_error()) {
					$this->ultimoComando = array('comando' => $sql, 'resultado' => "Error: ".mysql_errno().": ".mysql_error());
				} else {
					$this->ultimoComando = array('comando' => $sql, 'resultado' => 'error');
				}
				return null;
			}
		}
	}
}
?>

Como se puede ver en el código, la conexión se establece en el constructor de la clase y se mantiene el enlace en la variable $conn, la cual se utilizará cada vez que se realice una consulta. También en este método se selecciona la base de datos que utilizaremos, y se guarda el enlace, aunque no lo utilizaremos por el momento.

Se puede destacar la cláusula die() que se encarga de detener la ejecución del script, en este caso no nos interesa que se siga ejecutándo nuestro código si no pudimos establecer una conexión a la base de datos o no se obtuvo acceso a la base deseada.

Luego tenemos el destructor que se encarga solamente de cerrar la conexión, ésto se hace para liberar recursos en el servidor, lo cual puede llegar a ahorrarnos varios dolores de cabeza si la carga del servidor es muy grande.

Finalmente tenemos las funciones que trabajan sobre los datos, de éstas funciones voy a explicar un poco lo que hacen, ya que el código es muy simple y asumo que tenemos conocimientos por lo menos básicos de lenguaje SQL.

Las funciones que trabajan con los datos están escritas de forma muy similar, y la principal diferencia entre una y otra es la sentencia SQL que se utilizará. Hemos incluido un manejo precario de errores, que nos permitirá saber por qué no se ejecutó una determinada consulta.

Finalmente tenemos que probarla por lo que les recomiendo que descarguen el código fuente desde este enlace, en el archivo encontrarán la clase, un script para probar nuestra clase, y un script para la creación de la base de datos. Éste último fue generado con phpMyAdmin, para quienes no lo conocen, es un front -end para MySQL escrito en php.

Si alguien desea aportar algo o hacer alguna consulta no duden en dejar un comentario o enviar un mensaje usando el formulario de contacto.

Descargar el ejemplo de conexión a MySQL con PHP (2.05 KB)

}


Página 1 de 212»