jueves, 20 de mayo de 2010

Serialización de clases derivadas

Al referirme a clases derivadas me refiero a clases que heredan ya sea de interfaces, clases abstractas o clases concretas, al serializar este tipo de clases muy amplias utilizando la herencia es un poco complejo el estar "marcando" por clase que es un atributo o que es una clase raíz y cosas así para después su serialización, entonces existe una forma que nos permite hacer este trabajo muy cómodamente y sin tener que estar marcando cada clase con atributos y demás. Esta forma consiste en personalizar la serializacion de objetos, utilizando:

XmlAttributes

XmlElementAttribute

XmlAttributeOverrides

XmlSerializer

Supongamos que tenemos esta jerarquia de clases:

public class Name
{


public Name() { }


public Name(string Name, string _1erApellido, string _2doApellido)
{
nombre = Name;

primerApellido = _1erApellido;

segundoApellido = _2doApellido;

}

public stringnombre { set;get;}

public string primerApellido {


set; get; }


public
string segundoApellido { set; get; }


public
override
string ToString()

{


return nombre + " " + primerApellido + " " + segundoApellido;

}

}

public class Persona {


public Persona() { }


public Persona(Name Nombre, string fechaNacimiento)

{


this.Nombre = Nombre;


this.FechaNacimiento = fechaNacimiento;

}


public
Name Nombre { get; set; }


public
string FechaNacimiento { get; set; }

}

public
class
PersonaFisica:Persona

{


public
string RazonSocial { set; get; }


public
string homoClave { set; get; }


public PersonaFisica() { }


public PersonaFisica(Name _nombre, string _fechaNacimiento, string homoclave)

: base(_nombre, _fechaNacimiento)

{


this.homoClave = homoclave; this.RazonSocial = Nombre.ToString();


 

}

}

public class Interprete

{


public
string Nombre { set; get; }

}

public
class
Disco

{


public Disco() { }


public
string Titulo { set; get; }


public
Interprete Interprete { set; get; }


public
string Clasificacion { set; get; }


public
string TipoDisco { set; get; }

}

[XmlRootAttribute("prestamo")]
public class Prestamo{



public Prestamo(){}


public Prestamo(PersonaFisica Cliente,Disco Articulo)

{

DatosCliente = Cliente;

ArticuloAPrestar = Articulo;

fechaInicio = DateTime.Now.ToString(); ;

}


public
PersonaFisica DatosCliente { set; get; }


public
Disco ArticuloAPrestar { set; get; }


public
string fechaInicio { set; get; }

}

Ahora bien, como se puede dar uno cuenta,estas clases estan bastantes creciditas,donde una implementa a todas,la serializacion se vuelve un tanto ruda porque se estan utilizando clases sobre clases y asi sucesivamente, ahora bien para serializar todas estas a la vez,nos ayudamos de nuestros amigos mencionados anteriormente, primero, necesitamos instanciar Un objeto XmlAttributes y un XmlElementAttribute:

XmlAttributes atribXml = new
XmlAttributes();

XmlElementAttribute elemntAtrib = new
XmlElementAttribute();

A la propiedad Type de "elemntAtrib"(XmlElementAttribute) se le asigna el tipo de dato que queremos serizalizar, en este caso seria de tipo Prestamo.

elemntAtrib.Type = typeof(Prestamo);

Despues al objeto" atribXml " de tipo XmlAttributes le agregamos un elemento XmlElementAttribute:

atribXml.XmlElements.Add(elemntAtrib);

Ahora bien, despues de esto vamos a necesitar reemplazar el modo predeterminado de serializar los objetos, y esto lo hacemos instanciando un objeto de tipo "XmlAttributeOverrides",que es lo que necesitamos para nuestros fines.

XmlAttributeOverrides atribSobreEscrito = new
XmlAttributeOverrides();

Mediante el metodo Add agregamos un objeto XmlAttributes.

atribSobreEscrito.Add(typeof(List<Prestamo>), atribXml);

NOTA: al agregar un XmlAttributes necesitamos especificar el tipo de dato del cual queremos serializar, en este caso es una lista generica que guarda objetos de tipo Prestamo,seguido del objeto XmlAttributes que hemos creado.

Ahora bien, ya que tenemos todas las piezas del puzzle solo tenemos que llamar a la clase magica que hace el trabajo y para eso instanciamos un objetito de esta:

XmlSerializer serializer = new
XmlSerializer(typeof(List<Prestamo>), atribSobreEscrito);

Y por ultimo vamos a escribir sobre el archivo.


 

TextWriter writer = new
StreamWriter(@"C:\\Prestamos.xml");

Y serializar:

serializer.Serialize(writer, Prestamos);

writer.Close();

codigo Serializar:

XmlAttributes atribXml = new XmlAttributes();
XmlElementAttribute elemntAtrib = new
XmlElementAttribute();

elemntAtrib.Type = typeof(Prestamo);

atribXml.XmlElements.Add(elemntAtrib);


XmlAttributeOverrides atribSobreEscrito = new
XmlAttributeOverrides();

atribSobreEscrito.Add(typeof(List<Prestamo>), atribXml);


XmlSerializer serializer =new
XmlSerializer(typeof(List<Prestamo>), atribSobreEscrito);


TextWriter writer = new
StreamWriter(@"C:\\Prestamos.xml");

serializer.Serialize(writer, Prestamos);

writer.Close();

Por ultimo para deserializar el objeto es similar:

Codigo Deserializar:

     ///, se instancia un objeto XmlAttributeOverrides, XmlAttributes, XmlElementAttribute

XmlAttributeOverrides atribSobreEscrito = new
XmlAttributeOverrides();


XmlAttributes atribXml = new
XmlAttributes();


XmlElementAttribute elemntAtrib = new
XmlElementAttribute();

elemntAtrib.Type = typeof(Prestamo);

atribXml.XmlElements.Add(elemntAtrib);

atribSobreEscrito.Add(typeof(List<Prestamo>), atribXml);


XmlSerializer serializer = new
XmlSerializer(typeof(List<Prestamo>), atribSobreEscrito);


FileStream fsFile = new
FileStream(path, FileMode.Open);//se abre el archivo en el path especificado para leerlo

Prestamos = (List<Prestamo>) serializer.Deserialize(fsFile);//Prestamos es una lista de prestamos(List<Prestamo>)), a esta se le asignan los elementos que se deserealizan del archivo.

Y bueno espero que se entienda la explicacion a grandes rasgos.

Saludos.

sábado, 15 de mayo de 2010

Acceder a una bd Access

Vamos a acceder a una base de datos de access y el pekeño ejemplo abarca la insercion, eliminacion y show de datos, esto con solo dos campitos, ID y Nombre en una tabla llamada "tabla1".

codigo:
using System;
using System.Data.OleDb;
using System.Data;
using System.Windows.Forms;

namespace example_bd
{
public partial class Form1 : Form
{ //Se declara un string que indica el provedor, el path y la protección del acceso al origen de datos.
string namedb = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Example.accdb;Persist Security Info=False";
string SentTbTabla = "SELECT * FROM Tabla1 ORDER BY ID";//query
OleDbConnection conexion;//se declara la conexion que utilizaremos
OleDbDataAdapter daComplemnt;//se declara un adaptador de datos
OleDbCommandBuilder creation;//se declara un commanbuilder para agregar comportamientos como insertar,eliminar actualizar etc, al dataAdapter.
DataTable dtTabla1;//se declara una tabla
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
//conexion con la bd access
conexion= new OleDbConnection(namedb);
//se crea el adaptador
daComplemnt = new OleDbDataAdapter(SentTbTabla, conexion);
//se crea el commandbuilder para asignar los comandos update,delete,insert al dataAdapter
creation = new OleDbCommandBuilder(daComplemnt);
//se crean las tablas
dtTabla1 = new DataTable();
//se le agregan los siguientes comportamientos al dataAdapter, aunque se supone que se realiza automaticamente luego surgen problemas internos y no lo hace..:]
daComplemnt.UpdateCommand = creation.GetUpdateCommand();
daComplemnt.DeleteCommand = creation.GetDeleteCommand();
daComplemnt.Fill(dtTabla1 );

}
private void btnMostrar_Click(object sender, EventArgs e)
{
if(txtID.Text !="")//valida que no este vacio el textbox.
{
//se realiza la extraccion de los campos de la bd
DataRow[] foundRows;
//busca la columna que tenga un determinado ID dado por el usuario en el txtID
foundRows = dtTabla1.Select("ID=" + "'" + txtID .Text + "'");
//se muestra en txtName el valor del nombre con el ID dado por el usuario
txtName.Text = foundRows[0].ItemArray[1] + "";
}
}
private void btnDelate_Click(object sender, EventArgs e)
{
DataRow[] foundRows;
//Se busca una fila atravez de un valor de columna ID
foundRows = dtTabla1.Select("ID=" + "'" + txtID.Text + "'");
//se elimina
foundRows[0].Delete();
//se realiza la actualizacion a la bd
daComplemnt.Update(dtTabla1);
//aceptar cambios para que surta efecto directo en la bd
dtTabla1.AcceptChanges();
MessageBox.Show("hecho");
txtID.Text = "";
txtName.Text = "";
}
private void btnInsertar_Click(object sender, EventArgs e)
{
//se crea una nueva DataRow
DataRow drComplemnt = dtTabla1.NewRow();
//se agregan en cada campito los valores de los textbox
drComplemnt["ID"] = txtID.Text;
drComplemnt["Nombre"] = txtName.Text;
//se agrega a la tabla la columna llenada anteriormente
dtTabla1.Rows.Add(drComplemnt);
//update a la bd
daComplemnt.Update(dtTabla1);
// aceptar cambios para que surta efecto directo en la bd
dtTabla1.AcceptChanges();
MessageBox.Show("hecho");
txtID.Text = "";
txtName.Text = "";
}
}
}

descargate el proyecto con la bd de ejemplo:
http://www.megaupload.com/?d=14QIN1KS