El Libro del Día: 2015-06-26
Titulo: Pro REST API Development with Node.js
Autor: Fernando Doglio
Editorial: Apress
Nro Paginas: 191
Capítulos:
Chapter 1: Rest 101
Chapter 2: API Design Best Practices
Chapter 3: Node.js and REST
Chapter 4: Architecting a REST API
Chapter 5: Working with Modules
Chapter 6: Planning Your REST API
Chapter 7: Developing Your REST API
Chapter 8: Troubleshooting
Descarga:
Pro_REST_API_Development_with_Node.js
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.
viernes, 26 de junio de 2015
El Libro del Día: Pro REST API Development with Node.js
Etiquetas:
API,
Apress,
Architecting,
Best Practices,
Design,
Developing,
Development,
Fernando Doglio,
Libros,
Modules,
Node.js,
Planning,
REST,
Rest 101,
REST API,
Troubleshooting
jueves, 25 de junio de 2015
Videos - Google I/O 2015
Videos del Google I/O 2015
Comparto con ustedes el evento mas importante de Google llamado I/O en su versión 2015.
Las sesiones son sobre Cloud Messaging, Android, Analytics, Games, Material Design, Polymer, FireBase, Play Services, Google Play, Android Wear, iOS, etc.
1. Keynote
2. Google Cloud Messaging 3.0
3. What's new in Android
4. What's New in Android Development Tools
5. Smarter monetization with AdMob and Analytics
6. The next generation mobile web
7. Growing games with Google
8. Material Now
9. Android Pay: The next generation of payments on Android
10. Polymer and modern web APIs: In production at Google scale
11. Smarter user acquisition with App Indexing, AdWords and Google Analytics
12. Project Tango - Mobile 3D tracking and perception
13. Developing Extraordinary Apps with Firebase
14. Designing for virtual reality
15. What's new in Google Play services
16. Improve your Android app's accessibility
17. Developers connecting the world through Google Play
18. Ubiquitous Computing with Google
19. Android Wear: Your app and the always-on screen
20. Developing with Google on iOS
Comparto con ustedes el evento mas importante de Google llamado I/O en su versión 2015.
Las sesiones son sobre Cloud Messaging, Android, Analytics, Games, Material Design, Polymer, FireBase, Play Services, Google Play, Android Wear, iOS, etc.
1. Keynote
2. Google Cloud Messaging 3.0
3. What's new in Android
4. What's New in Android Development Tools
5. Smarter monetization with AdMob and Analytics
6. The next generation mobile web
7. Growing games with Google
8. Material Now
9. Android Pay: The next generation of payments on Android
10. Polymer and modern web APIs: In production at Google scale
11. Smarter user acquisition with App Indexing, AdWords and Google Analytics
12. Project Tango - Mobile 3D tracking and perception
13. Developing Extraordinary Apps with Firebase
14. Designing for virtual reality
15. What's new in Google Play services
16. Improve your Android app's accessibility
17. Developers connecting the world through Google Play
18. Ubiquitous Computing with Google
19. Android Wear: Your app and the always-on screen
20. Developing with Google on iOS
Etiquetas:
Analytics,
Android,
Android Wear,
Cloud Messaging,
FireBase,
Games,
Google,
Google Play,
I/O,
iOS,
Material Design,
Play Services,
Polymer,
Videos
El Libro del Día: HTML5, JavaScript, and jQuery
El Libro del Día: 2015-06-25
Titulo: HTML5, JavaScript, and jQuery. 24 Hour Trainer
Autor: Dane Cameron
Editorial: Wrox
Nro Paginas: 411
Capítulos:
PART I: HTML AND CSS
LESSON 1: INTRODUCTION TO HTML5
LESSON 2: BASIC HTML
LESSON 3: LISTS AND TABLES
LESSON 4: INTRODUCTION TO CSS
LESSON 5: STRUCTURING PAGES WITH CSS
LESSON 6: HTML FORMS
LESSON 7: SEMANTIC TAGS
LESSON 8: HTML5 VALIDATION
LESSON 9: DRAG AND DROP
LESSON 10: DYNAMIC ELEMENTS
PART II: DYNAMIC HTML5 WEB APPLICATIONS WITH JAVASCRIPT AND JQUERY
LESSON 11: JAVASCRIPT 95
LESSON 12: DEBUGGING
LESSON 13: FUNCTIONS
LESSON 14: OBJECTS
LESSON 15: JSON
LESSON 16: DOCUMENT OBJECT MODEL
LESSON 17: JQUERY SELECTION
LESSON 18: JQUERY TRAVERSAL AND MANIPULATION
LESSON 19: JQUERY EVENTS
LESSON 20: DATA ATTRIBUTES AND TEMPLATES
LESSON 21: JQUERY PLUGINS
PART III: HTML5 MULTIMEDIA
LESSON 22: HTML5 AUDIO
LESSON 23: HTML5 VIDEO
LESSON 24: CANVAS: PART I
LESSON 25: CANVAS: PART II
LESSON 26: CSS3: PART I
LESSON 27: CSS3: PART II
LESSON 28: CSS3 MEDIA QUERIES
PART IV: HTML5 APIS
LESSON 29: WEB SERVERS
LESSON 30: WEB STORAGE
LESSON 31: INDEXEDDB
LESSON 32: APPLICATION CACHE
LESSON 33: WEB WORKERS
LESSON 34: FILES
LESSON 35: AJAX
LESSON 36: PROMISES
PART V: MOBILE
LESSON 37: RESPONSIVE WEB DESIGN
LESSON 38: LOCATION API
LESSON 39: JQUERY MOBILE: PART I
LESSON 40: JQUERY MOBILE: PART II
Descarga:
HTML5_JavaScript_and_jQuery_24_Hour_Trainer
Titulo: HTML5, JavaScript, and jQuery. 24 Hour Trainer
Autor: Dane Cameron
Editorial: Wrox
Nro Paginas: 411
Capítulos:
PART I: HTML AND CSS
LESSON 1: INTRODUCTION TO HTML5
LESSON 2: BASIC HTML
LESSON 3: LISTS AND TABLES
LESSON 4: INTRODUCTION TO CSS
LESSON 5: STRUCTURING PAGES WITH CSS
LESSON 6: HTML FORMS
LESSON 7: SEMANTIC TAGS
LESSON 8: HTML5 VALIDATION
LESSON 9: DRAG AND DROP
LESSON 10: DYNAMIC ELEMENTS
PART II: DYNAMIC HTML5 WEB APPLICATIONS WITH JAVASCRIPT AND JQUERY
LESSON 11: JAVASCRIPT 95
LESSON 12: DEBUGGING
LESSON 13: FUNCTIONS
LESSON 14: OBJECTS
LESSON 15: JSON
LESSON 16: DOCUMENT OBJECT MODEL
LESSON 17: JQUERY SELECTION
LESSON 18: JQUERY TRAVERSAL AND MANIPULATION
LESSON 19: JQUERY EVENTS
LESSON 20: DATA ATTRIBUTES AND TEMPLATES
LESSON 21: JQUERY PLUGINS
PART III: HTML5 MULTIMEDIA
LESSON 22: HTML5 AUDIO
LESSON 23: HTML5 VIDEO
LESSON 24: CANVAS: PART I
LESSON 25: CANVAS: PART II
LESSON 26: CSS3: PART I
LESSON 27: CSS3: PART II
LESSON 28: CSS3 MEDIA QUERIES
PART IV: HTML5 APIS
LESSON 29: WEB SERVERS
LESSON 30: WEB STORAGE
LESSON 31: INDEXEDDB
LESSON 32: APPLICATION CACHE
LESSON 33: WEB WORKERS
LESSON 34: FILES
LESSON 35: AJAX
LESSON 36: PROMISES
PART V: MOBILE
LESSON 37: RESPONSIVE WEB DESIGN
LESSON 38: LOCATION API
LESSON 39: JQUERY MOBILE: PART I
LESSON 40: JQUERY MOBILE: PART II
Descarga:
HTML5_JavaScript_and_jQuery_24_Hour_Trainer
Etiquetas:
AJAX,
Canvas,
CSS3,
Dane Cameron,
DOM,
Drag & Drop,
Forms,
HTML5,
IndexedDB,
Javascript,
jQuery,
JSON,
Libros,
Lists,
Media Queries,
Multimedia,
Tables,
Validation,
Web Storages,
Wrox
miércoles, 24 de junio de 2015
El Libro del Día: Beginning JavaScript
El Libro del Día: 2015-06-24
Titulo: Beginning JavaScript
Autor: Jeremy McPeak, Paul Wilton
Editorial: Wrox
Nro Paginas: 771
Capítulos:
Chapter 1: Introduction to JavaScript and the Web
Chapter 2: Data Types and Variables
Chapter 3: Decisions and Loops
Chapter 4: Functions and Scope
Chapter 5: JavaScript An Object Based Language
Chapter 6: String Manipulation
Chapter 7: Date, Time, and Timers
Chapter 8: Programming the Browser
Chapter 9: DOM Scripting
Chapter 10: Events
Chapter 11: HTML Forms: Interacting with the User
Chapter 12: JSON
Chapter 13: Data Storage
Chapter 14: Ajax
Chapter 15: HTML5 Media
Chapter 16: jQuery
Chapter 17: Other JavaScript Libraries
Chapter 18: Common Mistakes, Debugging, and Error Handling
Descarga:
Beginning_JavaScript
Titulo: Beginning JavaScript
Autor: Jeremy McPeak, Paul Wilton
Editorial: Wrox
Nro Paginas: 771
Capítulos:
Chapter 1: Introduction to JavaScript and the Web
Chapter 2: Data Types and Variables
Chapter 3: Decisions and Loops
Chapter 4: Functions and Scope
Chapter 5: JavaScript An Object Based Language
Chapter 6: String Manipulation
Chapter 7: Date, Time, and Timers
Chapter 8: Programming the Browser
Chapter 9: DOM Scripting
Chapter 10: Events
Chapter 11: HTML Forms: Interacting with the User
Chapter 12: JSON
Chapter 13: Data Storage
Chapter 14: Ajax
Chapter 15: HTML5 Media
Chapter 16: jQuery
Chapter 17: Other JavaScript Libraries
Chapter 18: Common Mistakes, Debugging, and Error Handling
Descarga:
Beginning_JavaScript
Etiquetas:
AJAX,
Beginning,
Browser,
Decisions,
DOM,
Events,
Forms,
Functions,
Javascript,
Jeremy McPeak,
jQuery,
JSON,
Libros,
Loops,
Paul Wilton,
String,
Timers,
Types,
Variables,
Wrox
martes, 23 de junio de 2015
El Libro del Día: Beginning Google Glass Development
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
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
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
Suscribirse a:
Entradas (Atom)










