El Libro del Día: 2015-06-23
Titulo: Beginning Google Glass Development
Autor: Jeff Tang
Editorial: Apress
Nro Paginas: 358
Capítulos:
Chapter 1: Getting Started
Chapter 2: Hello, Glass Your First GDK App
Chapter 3: Glass User Interface
Chapter 4: Camera and Image Processing
Chapter 5: Video: Basics and Applications
Chapter 6: Voice and Audio
Chapter 7: Networking, Bluetooth, and Social
Chapter 8: Location, Map, and Sensors
Chapter 9: Graphics, Animation, and Games
Chapter 10: The Mirror API
Descarga:
Beginning_Google_Glass_Development
Blog de Luis Dueñas dedicado a la difusión del Desarrollo en Microsoft .NET, Visual Studio, WinForms, WebForms, MVC, ASP .NET, jQuery, AJAX, HTML5, JavaScript, Móviles, etc. Encontrarás Libros, Demos, Artículos Técnicos, Entrenamiento.
martes, 23 de junio de 2015
El Libro del Día: Beginning Google Glass Development
Etiquetas:
Animation,
Apress,
Audio,
Beginning,
Bluetooth,
Camera,
GDK,
Google Glass,
Graphics,
Image Processing,
Jeff Tang,
Libros,
Location,
Map,
Networking,
Sensors,
Social,
UI,
Video,
Voice
lunes, 22 de junio de 2015
El Libro del Día: Beginning JSON
El Libro del Día: 2015-06-22
Titulo: Beginning JSON
Autor: Ben Smith
Editorial: Apress
Nro Paginas: 353
Capítulos:
Chapter 1: JavaScript Basics
Chapter 2: Special Objects
Chapter 3: String Manipulation
Chapter 4: Introducing JSON
Chapter 5: Creating JSON
Chapter 6: Parsing JSON
Chapter 7: Persisting JSON: I
Chapter 8: Data Interchange
Chapter 9: X-Origin Resources
Chapter 10: Serving JSON
Chapter 11: Posting JSON
Chapter 12: Persisting JSON: II
Chapter 13: Working with Templates
Chapter 14: Putting It All Together
Descarga:
Beginning_JSON
Titulo: Beginning JSON
Autor: Ben Smith
Editorial: Apress
Nro Paginas: 353
Capítulos:
Chapter 1: JavaScript Basics
Chapter 2: Special Objects
Chapter 3: String Manipulation
Chapter 4: Introducing JSON
Chapter 5: Creating JSON
Chapter 6: Parsing JSON
Chapter 7: Persisting JSON: I
Chapter 8: Data Interchange
Chapter 9: X-Origin Resources
Chapter 10: Serving JSON
Chapter 11: Posting JSON
Chapter 12: Persisting JSON: II
Chapter 13: Working with Templates
Chapter 14: Putting It All Together
Descarga:
Beginning_JSON
Etiquetas:
Apress,
Beginning,
Ben Smith,
Creating,
Data,
Interchange,
Javascript,
JSON,
Libros,
Objects,
Parsing,
Persisting,
Posting,
Resources,
Serving,
String,
Templates
viernes, 19 de junio de 2015
El Demo del Día: Aumentar Funcionalidad en una Aplicación WinForms usando Reflection (Sin Recompilar)
Aumentar Funcionalidad en una Aplicación WinForms usando Reflection (Sin Recompilar)
El Problema de la Actualización de Aplicaciones
Cada vez que se crea una Aplicación Windows se distribuye el ejecutable en las diferentes PCs de los usuarios que van a usar la aplicación.
Solución Actual al Problema de la Actualización de Aplicaciones
Si deseamos realizar cambios, sobre todo aumentar nueva funcionalidad, existen 2 soluciones comunes:
1. Recuperar los fuentes (código fuente), aumentar la funcionalidad, recompilar y volver a distribuir.
Problema: Si no se tiene los fuentes, porque muchas veces se compra solo el ejecutable (por dismunir costos) no se podría usar esta técnica.
2. Ejecutar desde el Módulo Principal los demás Módulos, es decir una aplicación preparada para ejecutar cualquier exe (los módulos)
Problema: No hay un control interno de las ventanas de los módulos que se ejecuten, por ejemplo que aparezcan dentro del MDI Principal, se puedan organizar y sobre todo el intercambio de datos.
Solución Propuesta al Problema de la Actualización de Aplicaciones
Construir un Sistema Principal que pueda ejecutar cualquier módulo, ya sea una aplicación o una librería, para eso usaremos Reflection.
Las 3 tareas a realizar desde el menú principal del sistema serían:
1. Ejecutar formularios (clases) desde cualquier ensamblado
2. Ejecutar procesos (exe) como por ejemplo utilitarios del sistema
3. Ejecutar métodos (funciones públicas) de cualquier clase de cualquier ensamblado
Con esta aproximación, para aumentar nueva funcionalidad solo basta hacer 2 cosas:
1. Aumentar en tablas (en nuestro caso un archivo de texto) las nuevas opciones del menú
2. Copiar el o los archivos exe (módulos de procesos, usables también independientemente) y archivos dll (módulos de librerías, usables solo por el módulo principal u otras aplicaciones).
Componentes del Demo
Este demo tiene los siguientes componentes (archivos):
1. Menus.txt: Archivo de texto con las opciones del menú principal a cargar.
2. SistemaPrincipal.exe: La aplicación principal (WinForms) que tiene un MDI con el código que permite cargar los menús y a través de este abrir cualquier formulario, ejecutar procesos y ejecutar métodos.
3. ModuloProcesos.exe: Una aplicación WinForms que contiene 2 formularios que van a aumentarse al Sistema Principal. También puede ejecutarse por si sola y muestra un formulario con dos opciones.
4. ModuloReportes.dll: Una librería conteniendo 2 formularios y una clase Rutinas con un método.
Crear la Aplicación Windows Forms con el Sistema Principal
Abrir Visual Studio y crear una aplicación Windows Forms en C# llamada "SistemaPrincipal", cambiarle de nombre al formulario por "frmPrincipal", configurar su propiedad IsMdiContainer en true y realizar el diseño similar a la figura mostrada:
Agregar 4 formularios al proyecto (configurar su propiedad BackColor en Red), con los siguientes nombres:
- frmConProdCat.cs: Propiedad Text en "Consulta de Productos por Categoria"
- frmConProdProv.cs: Propiedad Text en "Consulta de Productos Proveedor"
- frmManCliente.cs: Propiedad Text en "Mantenimiento de Clientes"
- frmManEmpleado.cs: Propiedad Text en "Mantenimiento de Empleados"
Crear una Clase Entidad de Negocio para el Menú
Agregar una clase al proyecto llamada: "beMenu" y escribir el siguiente código:
using System;
namespace SistemaPrincipal
{
public class beMenu
{
public string IdMenu { get; set; }
public string Titulo { get; set; }
public string Ensamblado { get; set; }
public string Accion { get; set; }
public string IdPadre { get; set; }
}
}
using System;
using System.Text;
using System.IO;
using System.Collections.Generic;
namespace SistemaPrincipal
{
public class saMenu
{
public List<beMenu> Listar(string NombreArchivo)
{
List<beMenu> lbeMenu = null;
if (File.Exists(NombreArchivo))
{
using (StreamReader sr = new StreamReader(NombreArchivo, Encoding.Default))
{
string[] menu;
lbeMenu = new List<beMenu>();
beMenu obeMenu;
while (!sr.EndOfStream)
{
menu = sr.ReadLine().Split(',');
obeMenu = new beMenu();
obeMenu.IdMenu = menu[0];
obeMenu.Titulo = menu[1];
obeMenu.Ensamblado = menu[2];
obeMenu.Accion = menu[3];
obeMenu.IdPadre = menu[4];
lbeMenu.Add(obeMenu);
}
}
}
return (lbeMenu);
}
}
}
using System;
using System.Collections.Generic;
namespace SistemaPrincipal
{
public class brMenu
{
public List<beMenu> Listar()
{
List<beMenu> lbeMenu = null;
saMenu osaMenu = new saMenu();
lbeMenu = osaMenu.Listar("Menus.txt");
return (lbeMenu);
}
}
}
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
namespace SistemaPrincipal
{
public partial class frmPrincipal : Form
{
List<beMenu> lbeMenu;
public frmPrincipal()
{
InitializeComponent();
}
private void llenarMenus(object sender, EventArgs e)
{
brMenu obrMenu = new brMenu();
lbeMenu = obrMenu.Listar();
List<beMenu> lbeRaiz = lbeMenu.FindAll(x=>x.IdPadre.Equals("0"));
ToolStripMenuItem mnuRaiz;
foreach(beMenu obeMenu in lbeRaiz)
{
mnuRaiz=new ToolStripMenuItem(obeMenu.Titulo);
mnuRaiz.Tag = String.Format("{0}|{1}", obeMenu.Accion, obeMenu.Ensamblado);
if (!obeMenu.Accion.Equals("")) mnuRaiz.Click += new EventHandler(ejecutarAccion);
mnuPrincipal.Items.Add(mnuRaiz);
crearSubMenu(obeMenu, mnuRaiz);
}
}
private void crearSubMenu(beMenu obeMenuPadre,ToolStripMenuItem mnuPadre)
{
List<beMenu> lbeMenuHijos =
lbeMenu.FindAll(x=>x.IdPadre.Equals(obeMenuPadre.IdMenu));
ToolStripMenuItem mnuHijo;
foreach (beMenu obeMenuHijo in lbeMenuHijos)
{
mnuHijo = new ToolStripMenuItem(obeMenuHijo.Titulo);
mnuHijo.Tag = String.Format("{0}|{1}", obeMenuHijo.Accion,
obeMenuHijo.Ensamblado);
if (!obeMenuHijo.Accion.Equals("")) mnuHijo.Click +=
new EventHandler(ejecutarAccion);
mnuPadre.DropDownItems.Add(mnuHijo);
crearSubMenu(obeMenuHijo, mnuHijo);
}
}
private void ejecutarAccion(object sender,EventArgs e)
{
ToolStripMenuItem mnu = (ToolStripMenuItem)sender;
string[] opciones = mnu.Tag.ToString().Split('|');
string accion = opciones[0];
string nombreEnsamblado = opciones[1];
if (accion.StartsWith("frm"))
{
Assembly ensamblado = Assembly.LoadFrom(nombreEnsamblado);
if (ensamblado != null)
{
Type tipo = ensamblado.GetType(String.Format("{0}.{1}",
Path.GetFileNameWithoutExtension(nombreEnsamblado),accion));
if (tipo != null)
{
object obj = Activator.CreateInstance(tipo);
if (obj != null)
{
Form frm = (Form)obj;
frm.MdiParent = this;
frm.Show();
}
}
}
}
else
{
if (accion.EndsWith(".exe"))
{
Process.Start(accion);
}
else
{
opciones = accion.Split('.');
accion = opciones[0];
string clase = opciones[1];
if (nombreEnsamblado.Equals("SistemaPrincipal.exe") &&
clase.Equals("frmPrincipal"))
{
MethodInfo mi = this.GetType().GetMethod(accion);
var rpta = mi.Invoke(this, null);
if (rpta != null) MessageBox.Show(rpta.ToString());
}
else
{
Assembly ensamblado = Assembly.LoadFrom(nombreEnsamblado);
if (ensamblado != null)
{
Type tipo = ensamblado.GetType(String.Format("{0}.{1}",
Path.GetFileNameWithoutExtension(nombreEnsamblado), clase));
if (tipo != null)
{
object obj = Activator.CreateInstance(tipo);
if (obj != null)
{
MethodInfo mi = tipo.GetMethod(accion);
if (mi != null)
{
var rpta = mi.Invoke(obj, null);
if (rpta != null) MessageBox.Show(rpta.ToString());
}
}
}
}
}
}
}
}
public void salirApp()
{
this.Close();
}
}
}
Nota: Asociar al evento "Load" del formulario "frmPrincipal" el método: "llenarMenus", el cual lista las opciones de la raíz o primer nivel, luego la función "crearSubMenu" recursivamente llena los demás niveles.
Crear el Archivo de Texto con las opciones del menu principal
Antes de crear el archivo de texto, hay que grabar y compilar la aplicación y luego ir a la carpeta "bin", "debug" y crear el archivo de texto "Menus.txt" similar a la figura mostrada:
Primera Prueba de la Aplicación Sistema Principal
Si se ejecuta la aplicación se mostrará el MDI con los menús cargados y si abrimos los formularios se mostrará similar a la siguiente figura:
Nota: La primera prueba consiste en mostrar solo las opciones que estan dentro del propio sistema (sin integración).
Crear otra Aplicación Windows Forms con el Módulo de Procesos
Crear una nueva aplicación Windows Forms en C# llamada "ModuloProcesos", cambiarle de nombre al formulario por "frmPrincipal" y configurar su propiedad BackColor en Green, y realizar el diseño similar a la figura mostrada:
Agregar 2 formularios al proyecto (configurar su propiedad BackColor en Green), con los siguientes nombres:
- frmNuevaOrden.cs: Propiedad Text en "Modulo de Procesos - Nueva Orden"
- frmNuevaFactura.cs: Propiedad Text en "Modulo de Procesos - Nueva Factura"
Escribir el siguiente código en el formulario "frmPrincipal":
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ModuloProcesos
{
public partial class frmPrincipal : Form
{
public frmPrincipal()
{
InitializeComponent();
}
private void btnNuevaOrden_Click(object sender, EventArgs e)
{
frmNuevaOrden frm = new frmNuevaOrden();
frm.WindowState = FormWindowState.Maximized;
frm.ShowDialog();
}
private void btnNuevaFactura_Click(object sender, EventArgs e)
{
frmNuevaFactura frm = new frmNuevaFactura();
frm.WindowState = FormWindowState.Maximized;
frm.ShowDialog();
}
private void btnSalirApp_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
Grabar y probar la aplicación ModuloProcesos.
Crear una Librería de Clases con el Módulo de Reportes
Crear una nueva Librería de Clases en C# llamada "ModuloReportes", cambiarle de nombre a la clase por "Rutinas.cs" y escribir el siguiente código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ModuloReportes
{
public class Rutinas
{
public string procesar()
{
return "Procesando";
}
}
}
Grabar y compilar la librería.
Nota: Esta No se puede ejecutar porque es una librería de clases, solo funciona desde una aplicación que la llame.
Segunda Prueba de la Aplicación Sistema Principal
Recuperar la aplicación "SistemaPrincipal", sacar una copia al archivo "Menus.txt" (carpeta bin, debug) y aumentar mas opciones al archivo, tal como se muestra en la siguiente figura:
Copiar los archivos ModuloProcesos.exe y ModuloReportes.dll hacia la carpeta bin, debug donde se encuentra la aplicación SistemaPrincipal.exe y el archivo Menus.txt.
Ejecutar nuevamnete la aplicación y se mostrará el MDI con los menús cargados (los cuales han aumentado) y si abrimos los formularios se mostrará similar a la siguiente figura:
Observe que cada color diferencia el ensamblado donde se encuentra el formulario:
- Rojo: Formularios de la Aplicación Sistema Principal
- Verde: Formularios de la Aplicación Modulo Procesos
- Azul: Formularios de la Librería de Clases Modulo Reportes
También observe que al seleccionar "Reportes", "Graficos", "Estadistica" se ejecuta un método externo "procesar" encontrado en la Librería de Clases "ModuloReportes.dll" y cuando se elige la opción "Salir" se ejecuta el método "salirApp" ubicado en la misma clase del formulario MDI.
Comentario Final
En este post, hemos visto como aumentar funcionalidad a una Aplicación Windows sin Recompilar la Aplicación usando Reflection. Los menús se han cargado usando un archivo de texto, pero en vez de este puede ser una tabla de una base de datos.
Si bien es cierto, el uso intensivo de Reflection (sobre todo llamadas en bucles), no es recomendable, existen muchos casos como en este, que nos sirven de gran ayuda.
Muchos desarrolladores, desconecen la importancia y la gran cantidad de usos que se pueden dar a Reflection, pero en este Blog siempre estamos dando a conocer su importancia para darle "inteligencia" a tus soluciones.
Video del Demo
Aquí les dejo, un video parecido al Demo posteado, con la diferencia que la aplicación SistemaPrincipal se llama Demo12, la aplicación ModuloProcesos se llama Demo13 y la librería ModuloReportes se llama Demo14, pero igual les puede servir de guia.
Descarga del Código
2015_06_19_DemoDia_SistemaPrincipal
El Problema de la Actualización de Aplicaciones
Cada vez que se crea una Aplicación Windows se distribuye el ejecutable en las diferentes PCs de los usuarios que van a usar la aplicación.
Solución Actual al Problema de la Actualización de Aplicaciones
Si deseamos realizar cambios, sobre todo aumentar nueva funcionalidad, existen 2 soluciones comunes:
1. Recuperar los fuentes (código fuente), aumentar la funcionalidad, recompilar y volver a distribuir.
Problema: Si no se tiene los fuentes, porque muchas veces se compra solo el ejecutable (por dismunir costos) no se podría usar esta técnica.
2. Ejecutar desde el Módulo Principal los demás Módulos, es decir una aplicación preparada para ejecutar cualquier exe (los módulos)
Problema: No hay un control interno de las ventanas de los módulos que se ejecuten, por ejemplo que aparezcan dentro del MDI Principal, se puedan organizar y sobre todo el intercambio de datos.
Solución Propuesta al Problema de la Actualización de Aplicaciones
Construir un Sistema Principal que pueda ejecutar cualquier módulo, ya sea una aplicación o una librería, para eso usaremos Reflection.
Las 3 tareas a realizar desde el menú principal del sistema serían:
1. Ejecutar formularios (clases) desde cualquier ensamblado
2. Ejecutar procesos (exe) como por ejemplo utilitarios del sistema
3. Ejecutar métodos (funciones públicas) de cualquier clase de cualquier ensamblado
Con esta aproximación, para aumentar nueva funcionalidad solo basta hacer 2 cosas:
1. Aumentar en tablas (en nuestro caso un archivo de texto) las nuevas opciones del menú
2. Copiar el o los archivos exe (módulos de procesos, usables también independientemente) y archivos dll (módulos de librerías, usables solo por el módulo principal u otras aplicaciones).
Componentes del Demo
Este demo tiene los siguientes componentes (archivos):
1. Menus.txt: Archivo de texto con las opciones del menú principal a cargar.
2. SistemaPrincipal.exe: La aplicación principal (WinForms) que tiene un MDI con el código que permite cargar los menús y a través de este abrir cualquier formulario, ejecutar procesos y ejecutar métodos.
3. ModuloProcesos.exe: Una aplicación WinForms que contiene 2 formularios que van a aumentarse al Sistema Principal. También puede ejecutarse por si sola y muestra un formulario con dos opciones.
4. ModuloReportes.dll: Una librería conteniendo 2 formularios y una clase Rutinas con un método.
Crear la Aplicación Windows Forms con el Sistema Principal
Abrir Visual Studio y crear una aplicación Windows Forms en C# llamada "SistemaPrincipal", cambiarle de nombre al formulario por "frmPrincipal", configurar su propiedad IsMdiContainer en true y realizar el diseño similar a la figura mostrada:
Agregar 4 formularios al proyecto (configurar su propiedad BackColor en Red), con los siguientes nombres:
- frmConProdCat.cs: Propiedad Text en "Consulta de Productos por Categoria"
- frmConProdProv.cs: Propiedad Text en "Consulta de Productos Proveedor"
- frmManCliente.cs: Propiedad Text en "Mantenimiento de Clientes"
- frmManEmpleado.cs: Propiedad Text en "Mantenimiento de Empleados"
Crear una Clase Entidad de Negocio para el Menú
Agregar una clase al proyecto llamada: "beMenu" y escribir el siguiente código:
using System;
namespace SistemaPrincipal
{
public class beMenu
{
public string IdMenu { get; set; }
public string Titulo { get; set; }
public string Ensamblado { get; set; }
public string Accion { get; set; }
public string IdPadre { get; set; }
}
}
Crear una Clase Agente de Servicio para el Menú
Agregar una clase al proyecto llamada: "saMenu" y escribir el siguiente código:
Agregar una clase al proyecto llamada: "saMenu" y escribir el siguiente código:
using System.Text;
using System.IO;
using System.Collections.Generic;
namespace SistemaPrincipal
{
public class saMenu
{
public List<beMenu> Listar(string NombreArchivo)
{
List<beMenu> lbeMenu = null;
if (File.Exists(NombreArchivo))
{
using (StreamReader sr = new StreamReader(NombreArchivo, Encoding.Default))
{
string[] menu;
lbeMenu = new List<beMenu>();
beMenu obeMenu;
while (!sr.EndOfStream)
{
menu = sr.ReadLine().Split(',');
obeMenu = new beMenu();
obeMenu.IdMenu = menu[0];
obeMenu.Titulo = menu[1];
obeMenu.Ensamblado = menu[2];
obeMenu.Accion = menu[3];
obeMenu.IdPadre = menu[4];
lbeMenu.Add(obeMenu);
}
}
}
return (lbeMenu);
}
}
}
Nota: Para los que no conocen la terminología distribuida, si la clase es de datos es da: DataAccess, pero si trabajamos con recursos que no son bases de datos, como archivos de texto, la clase es sa: ServiceAgents (Agentes de Servicio).
Crear una Clase Regla de Negocio para el Menú
Agregar una clase al proyecto llamada: "brMenu" y escribir el siguiente código:
Agregar una clase al proyecto llamada: "brMenu" y escribir el siguiente código:
using System.Collections.Generic;
namespace SistemaPrincipal
{
public class brMenu
{
public List<beMenu> Listar()
{
List<beMenu> lbeMenu = null;
saMenu osaMenu = new saMenu();
lbeMenu = osaMenu.Listar("Menus.txt");
return (lbeMenu);
}
}
}
Escribir Código para el Formulario frmPrincipal
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
namespace SistemaPrincipal
{
public partial class frmPrincipal : Form
{
List<beMenu> lbeMenu;
public frmPrincipal()
{
InitializeComponent();
}
private void llenarMenus(object sender, EventArgs e)
{
brMenu obrMenu = new brMenu();
lbeMenu = obrMenu.Listar();
List<beMenu> lbeRaiz = lbeMenu.FindAll(x=>x.IdPadre.Equals("0"));
ToolStripMenuItem mnuRaiz;
foreach(beMenu obeMenu in lbeRaiz)
{
mnuRaiz=new ToolStripMenuItem(obeMenu.Titulo);
mnuRaiz.Tag = String.Format("{0}|{1}", obeMenu.Accion, obeMenu.Ensamblado);
if (!obeMenu.Accion.Equals("")) mnuRaiz.Click += new EventHandler(ejecutarAccion);
mnuPrincipal.Items.Add(mnuRaiz);
crearSubMenu(obeMenu, mnuRaiz);
}
}
private void crearSubMenu(beMenu obeMenuPadre,ToolStripMenuItem mnuPadre)
{
List<beMenu> lbeMenuHijos =
lbeMenu.FindAll(x=>x.IdPadre.Equals(obeMenuPadre.IdMenu));
ToolStripMenuItem mnuHijo;
foreach (beMenu obeMenuHijo in lbeMenuHijos)
{
mnuHijo = new ToolStripMenuItem(obeMenuHijo.Titulo);
mnuHijo.Tag = String.Format("{0}|{1}", obeMenuHijo.Accion,
obeMenuHijo.Ensamblado);
if (!obeMenuHijo.Accion.Equals("")) mnuHijo.Click +=
new EventHandler(ejecutarAccion);
mnuPadre.DropDownItems.Add(mnuHijo);
crearSubMenu(obeMenuHijo, mnuHijo);
}
}
private void ejecutarAccion(object sender,EventArgs e)
{
ToolStripMenuItem mnu = (ToolStripMenuItem)sender;
string[] opciones = mnu.Tag.ToString().Split('|');
string accion = opciones[0];
string nombreEnsamblado = opciones[1];
if (accion.StartsWith("frm"))
{
Assembly ensamblado = Assembly.LoadFrom(nombreEnsamblado);
if (ensamblado != null)
{
Type tipo = ensamblado.GetType(String.Format("{0}.{1}",
Path.GetFileNameWithoutExtension(nombreEnsamblado),accion));
if (tipo != null)
{
object obj = Activator.CreateInstance(tipo);
if (obj != null)
{
Form frm = (Form)obj;
frm.MdiParent = this;
frm.Show();
}
}
}
}
else
{
if (accion.EndsWith(".exe"))
{
Process.Start(accion);
}
else
{
opciones = accion.Split('.');
accion = opciones[0];
string clase = opciones[1];
if (nombreEnsamblado.Equals("SistemaPrincipal.exe") &&
clase.Equals("frmPrincipal"))
{
MethodInfo mi = this.GetType().GetMethod(accion);
var rpta = mi.Invoke(this, null);
if (rpta != null) MessageBox.Show(rpta.ToString());
}
else
{
Assembly ensamblado = Assembly.LoadFrom(nombreEnsamblado);
if (ensamblado != null)
{
Type tipo = ensamblado.GetType(String.Format("{0}.{1}",
Path.GetFileNameWithoutExtension(nombreEnsamblado), clase));
if (tipo != null)
{
object obj = Activator.CreateInstance(tipo);
if (obj != null)
{
MethodInfo mi = tipo.GetMethod(accion);
if (mi != null)
{
var rpta = mi.Invoke(obj, null);
if (rpta != null) MessageBox.Show(rpta.ToString());
}
}
}
}
}
}
}
}
public void salirApp()
{
this.Close();
}
}
}
Crear el Archivo de Texto con las opciones del menu principal
Antes de crear el archivo de texto, hay que grabar y compilar la aplicación y luego ir a la carpeta "bin", "debug" y crear el archivo de texto "Menus.txt" similar a la figura mostrada:
Primera Prueba de la Aplicación Sistema Principal
Si se ejecuta la aplicación se mostrará el MDI con los menús cargados y si abrimos los formularios se mostrará similar a la siguiente figura:
Nota: La primera prueba consiste en mostrar solo las opciones que estan dentro del propio sistema (sin integración).
Crear otra Aplicación Windows Forms con el Módulo de Procesos
Crear una nueva aplicación Windows Forms en C# llamada "ModuloProcesos", cambiarle de nombre al formulario por "frmPrincipal" y configurar su propiedad BackColor en Green, y realizar el diseño similar a la figura mostrada:
Agregar 2 formularios al proyecto (configurar su propiedad BackColor en Green), con los siguientes nombres:
- frmNuevaOrden.cs: Propiedad Text en "Modulo de Procesos - Nueva Orden"
- frmNuevaFactura.cs: Propiedad Text en "Modulo de Procesos - Nueva Factura"
Escribir el siguiente código en el formulario "frmPrincipal":
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ModuloProcesos
{
public partial class frmPrincipal : Form
{
public frmPrincipal()
{
InitializeComponent();
}
private void btnNuevaOrden_Click(object sender, EventArgs e)
{
frmNuevaOrden frm = new frmNuevaOrden();
frm.WindowState = FormWindowState.Maximized;
frm.ShowDialog();
}
private void btnNuevaFactura_Click(object sender, EventArgs e)
{
frmNuevaFactura frm = new frmNuevaFactura();
frm.WindowState = FormWindowState.Maximized;
frm.ShowDialog();
}
private void btnSalirApp_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
Crear una Librería de Clases con el Módulo de Reportes
Crear una nueva Librería de Clases en C# llamada "ModuloReportes", cambiarle de nombre a la clase por "Rutinas.cs" y escribir el siguiente código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ModuloReportes
{
public class Rutinas
{
public string procesar()
{
return "Procesando";
}
}
}
Hacer referencias a 2 librerías: System.Drawing.dll y System.Windows.Forms.dll
Agregar 2 formularios al proyecto (configurar su propiedad BackColor en Blue), con los siguientes nombres:
- frmRepCliente.cs: Propiedad Text en "Modulo de Reportes - Clientes"
- frmRepOrden.cs: Propiedad Text en "Modulo de Reportes - Ordenes"
- frmRepCliente.cs: Propiedad Text en "Modulo de Reportes - Clientes"
- frmRepOrden.cs: Propiedad Text en "Modulo de Reportes - Ordenes"
Grabar y compilar la librería.
Nota: Esta No se puede ejecutar porque es una librería de clases, solo funciona desde una aplicación que la llame.
Segunda Prueba de la Aplicación Sistema Principal
Recuperar la aplicación "SistemaPrincipal", sacar una copia al archivo "Menus.txt" (carpeta bin, debug) y aumentar mas opciones al archivo, tal como se muestra en la siguiente figura:
Copiar los archivos ModuloProcesos.exe y ModuloReportes.dll hacia la carpeta bin, debug donde se encuentra la aplicación SistemaPrincipal.exe y el archivo Menus.txt.
Ejecutar nuevamnete la aplicación y se mostrará el MDI con los menús cargados (los cuales han aumentado) y si abrimos los formularios se mostrará similar a la siguiente figura:
Observe que cada color diferencia el ensamblado donde se encuentra el formulario:
- Rojo: Formularios de la Aplicación Sistema Principal
- Verde: Formularios de la Aplicación Modulo Procesos
- Azul: Formularios de la Librería de Clases Modulo Reportes
También observe que al seleccionar "Reportes", "Graficos", "Estadistica" se ejecuta un método externo "procesar" encontrado en la Librería de Clases "ModuloReportes.dll" y cuando se elige la opción "Salir" se ejecuta el método "salirApp" ubicado en la misma clase del formulario MDI.
Comentario Final
En este post, hemos visto como aumentar funcionalidad a una Aplicación Windows sin Recompilar la Aplicación usando Reflection. Los menús se han cargado usando un archivo de texto, pero en vez de este puede ser una tabla de una base de datos.
Si bien es cierto, el uso intensivo de Reflection (sobre todo llamadas en bucles), no es recomendable, existen muchos casos como en este, que nos sirven de gran ayuda.
Muchos desarrolladores, desconecen la importancia y la gran cantidad de usos que se pueden dar a Reflection, pero en este Blog siempre estamos dando a conocer su importancia para darle "inteligencia" a tus soluciones.
Video del Demo
Aquí les dejo, un video parecido al Demo posteado, con la diferencia que la aplicación SistemaPrincipal se llama Demo12, la aplicación ModuloProcesos se llama Demo13 y la librería ModuloReportes se llama Demo14, pero igual les puede servir de guia.
Descarga del Código
2015_06_19_DemoDia_SistemaPrincipal
Etiquetas:
.NET,
Activator,
Archivos,
C#,
Demos,
Ensamblado,
Funcionalidad,
GetMethod,
GetType,
Invoke,
Lduenas,
Librerías,
Listas Objetos,
Menus,
Process,
Recompilar,
Reflection,
ToolStripMenuItem,
Video,
WinForms
El Libro del Día: Node.js Design Patterns
El Libro del Día: 2015-06-19
Titulo: Node.js Design Patterns
Autor: Mario Casciaro
Editorial: Packt
Nro Paginas: 454
Capítulos:
Chapter 1: Node.js Design Fundamentals
Chapter 2: Asynchronous Control Flow Patterns
Chapter 3: Coding with Streams
Chapter 4: Design Patterns
Chapter 5: Wiring Modules
Chapter 6: Recipes
Chapter 7: Scalability and Architectural Patterns
Chapter 8: Messaging and Integration Patterns
Descarga:
Node.js_Design_Patterns
Titulo: Node.js Design Patterns
Autor: Mario Casciaro
Editorial: Packt
Nro Paginas: 454
Capítulos:
Chapter 1: Node.js Design Fundamentals
Chapter 2: Asynchronous Control Flow Patterns
Chapter 3: Coding with Streams
Chapter 4: Design Patterns
Chapter 5: Wiring Modules
Chapter 6: Recipes
Chapter 7: Scalability and Architectural Patterns
Chapter 8: Messaging and Integration Patterns
Descarga:
Node.js_Design_Patterns
Etiquetas:
Architectural,
Asynchronous,
Control Flow,
Design Patterns,
Fundamentals,
Integration,
Libros,
Mario Casciaro,
Messaging,
Modules,
Node.js,
Packt,
Patterns,
Recipes,
Scalability,
Streams
jueves, 18 de junio de 2015
El Libro del Día: Practical Node.js
El Libro del Día: 2015-06-18
Titulo: Practical Node.js
Autor: Azat Mardan
Editorial: Apress
Nro Paginas: 288
Capítulos:
Chapter 1: Setting up Node.js and Other Essentials
Chapter 2: Using Express.js 4 to Create Node.js Web Apps
Chapter 3: TDD and BDD for Node.js with Mocha
Chapter 4: Template Engines: Jade and Handlebars
Chapter 5: Persistence with MongoDB and Mongoskin
Chapter 6: Using Sessions and OAuth to Authorize and Authenticate Users in Node.js Apps
Chapter 7: Boosting Your Node.js Data with the Mongoose ORM Library
Chapter 8: Building Node.js REST API Servers with Express.js and Hapi
Chapter 9: Real-Time Apps with WebSocket, Socket.IO, and DerbyJS
Chapter 10: Getting Node.js Apps Production Ready
Chapter 11: Deploying Node.js Apps
Chapter 12: Publishing Node.js Modules and Contributing to Open Source
Descarga:
Practical_Node.js
Titulo: Practical Node.js
Autor: Azat Mardan
Editorial: Apress
Nro Paginas: 288
Capítulos:
Chapter 1: Setting up Node.js and Other Essentials
Chapter 2: Using Express.js 4 to Create Node.js Web Apps
Chapter 3: TDD and BDD for Node.js with Mocha
Chapter 4: Template Engines: Jade and Handlebars
Chapter 5: Persistence with MongoDB and Mongoskin
Chapter 6: Using Sessions and OAuth to Authorize and Authenticate Users in Node.js Apps
Chapter 7: Boosting Your Node.js Data with the Mongoose ORM Library
Chapter 8: Building Node.js REST API Servers with Express.js and Hapi
Chapter 9: Real-Time Apps with WebSocket, Socket.IO, and DerbyJS
Chapter 10: Getting Node.js Apps Production Ready
Chapter 11: Deploying Node.js Apps
Chapter 12: Publishing Node.js Modules and Contributing to Open Source
Descarga:
Practical_Node.js
Etiquetas:
Apress,
Azat Mardan,
DerbyJS,
Express.js,
Handlebars,
Hapi,
Jade,
Libros,
Mocha,
MongoDB,
Mongoskin,
Node.js,
OAuth,
ORM Library,
REST API,
Sessions,
Socket.IO,
TDD & BDD,
Template Engines,
WebSocket
miércoles, 17 de junio de 2015
Entrenamiento - .NET Developer (The Best Practices for Performance)
.NET Developer (The Best Practices for Performance)
Comparto el contenido del nuevo Programa de Capacitación que estoy brindando para todos los interesados en profundizar sus conocimientos en la plataforma Microsoft .NET
Modulo 1: Windows Developer (72 horas en 3 meses)
Fundamentals
Curso 01: .NET Framework (18 horas)
Curso 02: ADO .NET (18 horas)
Windows Applications
Curso 03: WinForms (18 horas)
Curso 04: WPF (18 horas)
Modulo 2: Web Developer (72 horas en 3 meses)
Back End
Curso 05: ASP.NET MVC (18 horas)
Curso 06: Servicios (WCF y Web API) (18 horas)
Front End
Curso 07: JavaScript (DOM, jQuery, AJAX) (18 horas)
Curso 08: HTML5 (APIs) (18 horas)
Modulo 3: Mobile Developer (72 horas en 3 meses)
Web Mobile
Curso 09: Responsive Web Designe (CSS3+HTML5+MVC) (18 horas)
Curso 10: jQuery Mobile (18 horas)
Native Apps
Curso 11: Xamarin Forms iOS (18 horas)
Curso 12: Xamarin Forms Android (18 horas)
Hay 2 tipos de cursos:
- Cerrados para Empresas (Horarios de Lunes a Viernes en horarios a elegir)
- Libres para cualquier participante (Horarios: Sabados en la Tarde o Domingos en las Mañanas)
Ambos son 6 horas por semana, es decir 24 horas por mes, 3 meses por cada Módulo.
Los interesados enviar un mail a: Luis.duenash@gmail.com indicando lo siguiente:
- Nombre (curso Libre) o Empresa (curso Cerrado)
- Horario Seleccionado
- Fecha Inicio deseada (para Empresa)
En el mercado hay varias alternativas de capacitación en .NET, pero ninguna esta orientada a las Verdaderas Buenas Prácticas de Programación, sobre todo a la performance. En el programa se ve desde el inicio hasta el final como optimizar memoria y procesador.
Comparto el contenido del nuevo Programa de Capacitación que estoy brindando para todos los interesados en profundizar sus conocimientos en la plataforma Microsoft .NET
Modulo 1: Windows Developer (72 horas en 3 meses)
Fundamentals
Curso 01: .NET Framework (18 horas)
Curso 02: ADO .NET (18 horas)
Windows Applications
Curso 03: WinForms (18 horas)
Curso 04: WPF (18 horas)
Modulo 2: Web Developer (72 horas en 3 meses)
Back End
Curso 05: ASP.NET MVC (18 horas)
Curso 06: Servicios (WCF y Web API) (18 horas)
Front End
Curso 07: JavaScript (DOM, jQuery, AJAX) (18 horas)
Curso 08: HTML5 (APIs) (18 horas)
Modulo 3: Mobile Developer (72 horas en 3 meses)
Web Mobile
Curso 09: Responsive Web Designe (CSS3+HTML5+MVC) (18 horas)
Curso 10: jQuery Mobile (18 horas)
Native Apps
Curso 11: Xamarin Forms iOS (18 horas)
Curso 12: Xamarin Forms Android (18 horas)
Hay 2 tipos de cursos:
- Cerrados para Empresas (Horarios de Lunes a Viernes en horarios a elegir)
- Libres para cualquier participante (Horarios: Sabados en la Tarde o Domingos en las Mañanas)
Ambos son 6 horas por semana, es decir 24 horas por mes, 3 meses por cada Módulo.
Los interesados enviar un mail a: Luis.duenash@gmail.com indicando lo siguiente:
- Nombre (curso Libre) o Empresa (curso Cerrado)
- Horario Seleccionado
- Fecha Inicio deseada (para Empresa)
En el mercado hay varias alternativas de capacitación en .NET, pero ninguna esta orientada a las Verdaderas Buenas Prácticas de Programación, sobre todo a la performance. En el programa se ve desde el inicio hasta el final como optimizar memoria y procesador.
Etiquetas:
.NET,
.NET Developer,
Back End,
C#,
Capacitación,
Entrenamiento,
Front End,
Fundamentals,
HTML5,
Mobile Developer,
MVC,
Native Apps,
Performance,
Web Developer,
Web Mobile,
Windows Apps,
Windows Developer,
Xamarin
El Libro del Día: Professional Node.js
El Libro del Día: 2015-06-17
Titulo: Professional Node.js
Autor: Pedro Teixeira
Editorial: Wrox
Nro Paginas: 412
Capítulos:
PART I INTRODUCTION AND SETUP
CHAPTER 1 Installing Node
CHAPTER 2 Introducing Node
PART II NODE CORE API BASICS
CHAPTER 3 Loading Modules
CHAPTER 4 Using Buffers to Manipulate, Encode, and Decode Binary Data
CHAPTER 5 Using the Event Emitter Pattern to Simplify Event Binding
CHAPTER 6 Scheduling the Execution of Functions Using Timers
PART III FILES, PROCESSES, STREAMS, AND NETWORKING
CHAPTER 7 Querying, Reading from, and Writing to Files
CHAPTER 8 Creating and Controlling External Processes
CHAPTER 9 Reading and Writing Streams of Data
CHAPTER 10 Building TCP Servers
CHAPTER 11 Building HTTP Servers
CHAPTER 12 Building a TCP Client
CHAPTER 13 Making HTTP Requests
CHAPTER 14 Using Datagrams (UDP)
CHAPTER 15 Securing Your TCP Server with TLS/SSL
CHAPTER 16 Securing Your HTTP Server with HTTPS
PART IV BUILDING AND DEBUGGING MODULES AND APPLICATIONS
CHAPTER 17 Testing Modules and Applications
CHAPTER 18 Debugging Modules and Applications
CHAPTER 19 Controlling the Callback Flow
PART V BUILDING WEB APPLICATIONS
CHAPTER 20 Building and Using HTTP Middleware
CHAPTER 21 Making a Web Application Using Express.js
CHAPTER 22 Making Universal Real-Time Web Applications Using Socket.IO
PART VI CONNECTING TO DATABASES
CHAPTER 23 Connecting to MySQL Using node-mysql
CHAPTER 24 Connecting to CouchDB Using Nano
CHAPTER 25 Connecting to MongoDB Using Mongoose
Descarga:
Professional_Node.js
Titulo: Professional Node.js
Autor: Pedro Teixeira
Editorial: Wrox
Nro Paginas: 412
Capítulos:
PART I INTRODUCTION AND SETUP
CHAPTER 1 Installing Node
CHAPTER 2 Introducing Node
PART II NODE CORE API BASICS
CHAPTER 3 Loading Modules
CHAPTER 4 Using Buffers to Manipulate, Encode, and Decode Binary Data
CHAPTER 5 Using the Event Emitter Pattern to Simplify Event Binding
CHAPTER 6 Scheduling the Execution of Functions Using Timers
PART III FILES, PROCESSES, STREAMS, AND NETWORKING
CHAPTER 7 Querying, Reading from, and Writing to Files
CHAPTER 8 Creating and Controlling External Processes
CHAPTER 9 Reading and Writing Streams of Data
CHAPTER 10 Building TCP Servers
CHAPTER 11 Building HTTP Servers
CHAPTER 12 Building a TCP Client
CHAPTER 13 Making HTTP Requests
CHAPTER 14 Using Datagrams (UDP)
CHAPTER 15 Securing Your TCP Server with TLS/SSL
CHAPTER 16 Securing Your HTTP Server with HTTPS
PART IV BUILDING AND DEBUGGING MODULES AND APPLICATIONS
CHAPTER 17 Testing Modules and Applications
CHAPTER 18 Debugging Modules and Applications
CHAPTER 19 Controlling the Callback Flow
PART V BUILDING WEB APPLICATIONS
CHAPTER 20 Building and Using HTTP Middleware
CHAPTER 21 Making a Web Application Using Express.js
CHAPTER 22 Making Universal Real-Time Web Applications Using Socket.IO
PART VI CONNECTING TO DATABASES
CHAPTER 23 Connecting to MySQL Using node-mysql
CHAPTER 24 Connecting to CouchDB Using Nano
CHAPTER 25 Connecting to MongoDB Using Mongoose
Descarga:
Professional_Node.js
Etiquetas:
Buffers,
Emitter,
Event,
Files,
Functions,
HTTP Requests,
HTTP Servers,
Installing,
Libros,
Modules,
Node.js,
Pedro Teixeira,
Processes,
Professional,
Streams,
TCP Client,
TCP Servers,
Timers,
UDP,
Wrox
Suscribirse a:
Entradas (Atom)










