Category Archives: 4786

Aprovechamiento del área de notificación en Windows 7

Les dejo el link a mi aporte al programa Windows 7×7:

Aprovechamiento del área de notificación en Windows 7
En esta oportunidad quisiera mostrarte como aprovechar la funcionalidad que brinda Windows 7 en temas de interfaz de usuario. ¿Como hacemos para que nuestras aplicaciones pueda comunicarse con el usuario en el momento en que él no esta interatuando con ellas? Windows 7 propone, en la barra de tareas, una sección que se llama: Area de Notificaciones…..

Recursos adicionales:

 

CodeCamp – Buenos Aires 2008

Evento Académico gratuito con más de 40 conferencias sobre tecnologías Microsoft dicatadas por referentes de la industria.

Fecha:
Saturday, October 4, 2008
Hora:
10:00am – 7:00pm
Lugar:
UAI
Dirección:
San Juan 983
Ciudad:
Buenos Aires, Argentina
 
 

 

Descripción

• Novedades en Tecnologías Microsoft
• Más de 40 conferencias técnicas de Referentes de la Industria
• Sorteos entre los asistentes

Más detalles en el sitio del evento: http://www.microsoft.com.ar/codecamp/

Agenda:

10:00 a 10:30 Registración – Recepción

10:30 a 11:00 Apertura y revisión de agenda

11:15 a 12:15
Programando por un sueño – Patricio Jutard
Introducción a ASP.NET MVC – Pablo Cibraro
Videojuegos Multiplataforma con XNA – Augusto Chesini
Todo Lo Que Hay Que Saber Acerca De Linq – Matías Bonaventura
Mejoras De Desempeño De Aplicaciones .Net – Carlos Walzer
Gestión De Proyectos De Software: Un Enfoque Práctico – Maximiliano Menasches e Ignacio López
Windows Presentation Foundation Para Desarrolladores – Andres Aguiar
Python En La Plataforma .Net – Martín Salías
Introducción A Grafos – Pablo Gauna
Wamp – Maximo Naccarato
IIS7 4×4 – Alberto Ortega Y Horacio Gonzalez

12:30 a 13:30
Andamios en la web: Desarrollo ágil con ASP.NET Dynamic Data – Miguel Saez
Desarrollo web multi-capa con Volta: un paso hacia adelante – Pablo Zaidenvoren Y Rodolfo Finochietti
Wpf 3d Y Física – Damián Galletini
Microsoft Sql Server 2008 – Introducción A “Microsoft Sql Server Data Platform” – Johnny Halife
Patrones De Arquitectura Con C# – Matías Iacono
Vsts Y Scrum – Daniel Zacharias
Creando Aplicaciones En Wpf – José Villagrán
Parallel Extensions – Nicolás Padula Y Mauricio Lopez
Entorno De Desarrollo Para Windows Mobile 6 – Leonardo Natale
Windows Server 2008 + Iis 7 – Augusto Alvarez
Desmitificando Windows Vista – Mariano Rempel

13:30 a 14:45
Almuerzo – Demo Fest

15:00 a 16:00
El futuro de la ingeniería de software – Santiago Ceria
Silverlight 2.0 Beta 2 – Construyendo Aplicaciones Web Atractivas Utilizando Microsoft Silverlight – Ivana Tilca
3d Games Technology: Computer Animation – Diego Park
Ado.Net Entity Framework En Acción – Maximiliano Menasches Y Hernán Nobile
Técnicas Para Mejorar La Performance En Sitios Web – Juan Ladetto
Scrum – Patricio Jutard
¿Qué Es “Wpf/E”? – Luis Perdomo
Reconocimiento Facial – Armando Meabe
Novedades De Vs 2008 Y Cf 3.5 Para Wm6 – Leonardo Natale
Introducción A La Administración De Sucursales Con Windows Server 2008 – Leonardo Amaya
Seguridad En Windows Server 2008 – Leandro Amore

16:15 a 17:15
Hyper-V en acción – Alejandro Ponicke Y Leandro Amore
Expression Blend – Marcelo Quevedo
Qué Es Linq? – Guillermo Delfino
Programación Intuitiva De Xml En El Marco .Net (Xlinq) – Mauricio Grimberg
Howto: Performance Y Load Testing – Matias Woloski Y Federico Boerr
¿Cómo Lograr Un Proyecto Exitoso? – Patricia Scalzone
Construcción De Servicios Rest Con Wcf – Pablo Cibraro
Microsoft Robotics Studio – Mauro Castagnasso
Introducción A Los Conceptos De Generics Y Delegates – Ezequiel Cura
Monitoreo De Aplicaciones Heterogéneas – Alberto Ortega
Instalando Windows Vista – Francisco Moura

17:15 a 18:30
Break – Demo Fest

18:45 a 20:00
Cierre del Evento y Sorteos

Performance: Datos en Memoria con ADO.NET IV

En este artículo quisiera mostrarles cual es el consumo de memoria de algunas técnicas de acceso a datos. En artículos anteriores hemos estudiado y optimizado performance mejorando el tiempo de procesamiento. Como colorario veremos algunos gráficos que siempre ayudan a la comparación.

Este artículo está relacionado con:

Presentación del escenario

Este es el contexto en el que estoy haciendo las mediciones:

Una aplicación Windows Forms, que utiliza 4 mecanismos para recuperar datos “de solo lectura” de la base de datos AdvertureWorks alojada en SQL Server 2005:

  • DataReader cargado en una lista genérica de objetos de entidad
  • DataSet
  • DataTable
  • DataSet tipificado creado con el asistente de Visual Studio 2005

Aquí subrayo “solo lectura” porque, justamente solo quiero recuperar los datos, y no hacer ninguna operación sobre ellos.

Memoria y Garbage Collector

Si bien sabemos que la administración de la memoria en .NET es un trabajo que le compete al Garbage Collector y que no es terreno en el que debamos hurgar, a no ser que sea por administración de memoria no manejada, siempre es bueno saber que uso hacemos de él. Si bien el Garbage Collector es un mecanismo muy optimizado, y hace un muy buen trabajo de recolección de basura (memoria no utilizada), tiene sus limitaciones y su costo. Sería una buena actitud de parte nuestra considerar al Garbage Collector como un recurso más, así como lo es la memoria. Teniendo en cuenta esto lograríamos minimizar su trabajo, lo cual redundaría en un mejor rendimiento de nuestra aplicación.

El Código

La versión completa del código podrás bajarla de aquí. De todas formas démosle un vistazo:

Esta es la sentencia sql a ejecutar en la base de datos AdventureWorks:

Select HumanResources.Employee.EmployeeID, Person.Contact.FirstName,
          Person.Contact.MiddleName, Person.Contact.LastName,
          HumanResources.Employee.Title, HumanResources.Employee.BirthDate, 
          Person.Address.AddressLine1, Person.Address.AddressLine2, 
          Person.Address.City, Person.Address.PostalCode, Person.Contact.EmailAddress, 
          Person.Contact.Phone, HumanResources.Employee.MaritalStatus, HumanResources.Employee.Gender 
          FROM HumanResources.Employee
          INNER JOIN Person.Contact ON HumanResources.Employee.ContactID = Person.Contact.ContactID
          INNER JOIN HumanResources.EmployeeAddress ON HumanResources.Employee.EmployeeID = HumanResources.EmployeeAddress.EmployeeID
          INNER JOIN Person.Address ON HumanResources.EmployeeAddress.AddressID = Person.Address.AddressID
          AND HumanResources.EmployeeAddress.AddressID = Person.Address.AddressID

La clase DataAccess

public class DataAccess
{
   
static readonly string _connString;
   
static readonly string _sqlCmd;

    static DataAccess()
    {
        _connString =
“Password=;User ID=sa;Initial Catalog=AdventureWorks;Data Source=WALZER3”;
       
//Obtengo la sentencia SQL que está en el archivo de texto Consulta.sql
       
StreamReader sr = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(“Walzer.Antipracticas.Consulta.sql”));
        _sqlCmd = sr.ReadToEnd();
    }

    static public DataSet TraerDataSet()
    {
        
DataSet ds = null;
        
try
        
{
             
using (SqlConnection conn = new SqlConnection(_connString))
              {
                  conn.Open();
                 
SqlCommand cmd = new SqlCommand();
                  cmd.CommandText =
“GetEmployees”;
                  cmd.Connection = conn;
                  cmd.CommandType =
CommandType.StoredProcedure;
                 
SqlDataAdapter da = new SqlDataAdapter(cmd);
                  ds =
new DataSet();
                  da.Fill(ds);
              }
         }
        
catch
        
{
         }
        
return ds;
     }

     static public List<Employee> TraerEmployeesOptimizado()    
     {
    
     List<Employee> employees = new List<Employee>();
         
try
         
{
         
using (SqlConnection conn = new SqlConnection(_connString))
          {
             
SqlCommand cmd = new SqlCommand();
              cmd.CommandText =
“GetEmployees”;
              cmd.Connection = conn;
              cmd.CommandType =
CommandType.StoredProcedure;
              conn.Open();
             
using (SqlDataReader dr = cmd.ExecuteReader())
              {
                 
int colEmployeeId = dr.GetOrdinal(“EmployeeId”);
                 
int colFirstName = dr.GetOrdinal(“FirstName”);
                  // Omito las líneas similares por cuestión de lectura
                 
int colCount = dr.FieldCount;
                 
object[] values = new object[colCount];
                 
while (dr.Read())
                  {
                   
Employee employee = new Employee();
                    dr.GetValues(values);
                    employee.EmployeeID =
Convert.ToInt32(values[colEmployeeId]);
                    employee.FirstName =
Convert.ToString(values[colFirstName]);
                   
employees.Add(employee);
                  }
                }
             }
          }
         
catch
         
{
          }
         
return employees;
     }

     static public DataTable TraerDataTableOptimizado()
    
{
         
//Este método está optimizado para cargar un DataTable con datos de SOLO LECTURA
         
DataTable dt = null;
         
try
         
{
              
using (SqlConnection conn = new SqlConnection(_connString))
               {
                    conn.Open(); 
                   
SqlCommand cmd = new SqlCommand();cmd.CommandText = “GetEmployees”; 
                    cmd.Connection = conn; 
                    cmd.CommandType =
CommandType.StoredProcedure; 
                   
SqlDataAdapter da = new SqlDataAdapter(cmd);dt = new DataTable(); 
                    da.Fill(dt); 
               } 
          } 
          
catch 
          

          } 
          
return dt; 
     } 
}

El DataSet tipificado fue creado arrastrando la consulta SQL sobre la superficie de diseño del DataSet, lo único que escribí fue las siguientes líneas para cargar el DataSet tipificado:

DsEmployeesTableAdapters.GetEmployeesTableAdapter da = new Walzer.Antipracticas.DsEmployeesTableAdapters.GetEmployeesTableAdapter();
_dsEmployees = da.GetData();

Lectura del uso de Memoria

Vamos medir el uso de memoria de cada una de estas técnicas de acceso a datos utilizando 3 herramientas:

El CLR Profiler nos revela en una primera lectura de 290 registros representados en memoria por cada una de las técnicas.

En este gráfico podemos observar que el objeto del tipo AntiPracticas.frmMemoria, que es nuestra ventana, y sus referenciados consumen 836 Kb. Aunque la variable que apunta a esta estructura es de solo 368 bytes.

AntiPracticas.frmMemoria tiene cuatro campos privados que apuntan a:

  • un DataSet Tipado (DsEmployees.GetEmployeesDataTable): 313 Kb
  • un DataSet (Data.DataSet): 185 Kb
  • un DataTable (Data.DataTable ): 184 Kb
  • una colección genérica de objetos del tipo Employee (Generic.List<T>): 138 Kb

Aquí mismo podemos apreciar que el DataSetTipado es la estructura más costosa en cuanto a consumo de memoria. Que no hay casi diferencia entre un DataSet y un DataTable, y que la colección de objetos es la más barata. No está demás destacar que todas las estructuras contienen “los mismos datos”.

La misma información podemos verla en JetBrains DotTrace.


Observen la columna “Held Memory, bytes”, que es la memoria referenciada por cada instancia:

  • _dsEmployees (Walzer.Antipracticas.DsEmployees.GetEmployeesDataTable)
  • _ds (System.Data.DataSet)
  • _dt (System.Data.DataTable)
  • _employees (System.Collection.Generic.List<Employee>)

Estructura de Objetos en memoria

Comparemos en las siguientes dos capturas la complejidad de una y otra estructura, las cuales almacenan los mismos datos, de solo lectura en nuestro caso.

La primera figura nos muestra la lista genérica _employees, la cual está implementada internamente por un vector de _items, que contiene un conjunto de objetos Employee, la cual contiene finalmente los datos.

Observemos ahora la estructura de un DataSet tipificado, y el camino para llegar al dato final.

La estructura es mucho más compleja, pero no perdamos de vista que un DataSet fue diseñado con la premisa de propósito general, y mucho de su funcionalidad es útil. Debemos usar nuestro criterio a la hora de decidir que es mejor para nuestro sistema.

Inspeccionado contenido de las variables

Usemos ahora la herramienta .NET Memory Profiler para ver el contenido de un objeto del tipo Employee. Esta figura nos muestra las referencias a la que hace este objeto, que son System.String.

Pero, ¿dónde está el campo _idEmployee que es del tipo int o _birthDate que es de tipo DateTime? Bien, estos están contenidos en el mismo espacio de memoria que el objeto del tipo Employee ya que son tipos básicos, int y ulong respectivamente. En cambio System.String es una referencia al espacio de memoria donde está guardada la cadena de caracteres. La solapa Field Values nos muestra el contenido de la instancia #12,729 del objeto del tipo Employee. Además de esta información podemos apreciar, cuales son los caminos al Root de este objeto, y cuál fue el Call Stack que instanció este objeto en memoria.

Cantidad de Objetos referenciados

Un dato que no es menor aquí es el que nos muestra la columna “Held Objects”. Esta nos dice cuantos objetos son referenciados en toda la estructura en memoria.

En este caso la cantidad de filas en memoria para cada estructura es de 10, valor que se asemeja más a la realidad, ya que no es buena práctica pasar todas las filas del resultado entre capas, sino usar técnicas de paginación.

  • _dsEmployees (Walzer.Antipracticas.DsEmployees.GetEmployeesDataTable): 320
  • _ds (System.Data.DataSet): 213
  • _dt (System.Data.DataTable): 206
  • _employees (System.Collection.Generic.List<Employee>): 122

Más allá de la cantidad de memoria en bytes, la cantidad de objetos referenciados nos da una idea del trabajó que tendrá el Garbage Collector al momento de deshacerse de estos objetos. Cuantas más referencias en memoria, más recursos consumidos por este algoritmo.

Comparación de resultados

Veamos una serie de gráficos que resumen las lecturas realizadas. Tomé lecturas de 290 registros, 10 registros (que es el típico caso del tamaño de una página cuando se realiza paginación) y 1 registro.

 

Bytes en Memoria 290 reg 10 reg 1 reg
DataSet 189112 19028 14856
DataTable 188848 18764 14588
List<> 141774 4790 514
DataSet Tipado (wizard) 319478 33114 28902

 Fig1: Tabla Comparativa de Bytes en Memoria

Fig2: Bytes en memoria para 290 registros

Fig3: Bytes en memoria de 10 y 1 registro.

 

Referencias 290 reg 10 reg 1 reg
DataSet 3581 213 105
DataTable 3574 206 98
List<> 3477 122 13
DataSet Tipado (wizard) 3788 300 192

Fig4: Tabla Comparativa de Objetos Referenciados

Fig5: Instancias referenciadas para 290 registros

Fig6: Instancias referenciadas para 10 y 1 registro

Estos gráficos muestran claramente que la técnica más económica es pasar entre capas una lista genérica de un tipo específico. Y que la ferretería utilizada por las estructuras del tipo DataSet se puede despreciar cuanto mayor es el volumen que contienen.

Conclusión

Hemos comprobado que el uso correcto de las técnicas de acceso a datos en ADO.NET nos permite lograr un mayor rendimiento en nuestras aplicaciones. También hemos aprendido algo de cómo funciona internamente ADO.NET, y como son las estructuras en memoria y el uso que se hace de ellas.

Siempre es bueno conocer cómo funcionan internamente los frameworks que utilizamos para construir nuestras aplicaciones para poner en la balanza, facilidad y agilidad de uso contra rendimiento y consumo de recursos.

C# Desarrollo con Visual Studio 2005 [Extracto del Libro]

La Editorial Eni publicó el libro de C# Desarrollo con Visual Studio 2005, el cual traduje y adapté del Francés al Español.

Contenido del Libro 

Descargar los ejemplos del libro (1,05 Mo)

Aqui podrán ver un extracto del libro Capítulo 7 que trata de Windows Forms.

Nota: No hay un distribuidor en Sudamérica, con lo que la editorial recomienda dos opciones: 
1 )cursar una solicitud de presupuesto a través de nuestra web (tras lo cual se cotizan los gastos de envío, y el cliente acepta o no el pedido)
2) comprarlo a través de Celesa, www.celesa.com

Libro en Español: C# Desarrollo con Visual Studio 2005

La Editorial Eni publicó el libro de C# Desarrollo con Visual Studio 2005, el cual traduje y adapté del Francés al Español.

 

Autor : Hervé BERTHET
Adaptación al Español: Carlos Walzer
Revisón Técnica: Guillermo SOM
Presentación
Este libro se dirige a desarrolladores, incluso principiantes, que quieren dominar el lenguaje C# (Visual C#). El lector descubrirá la plataforma de desarrollo Visual Studio 2005, las bases del lenguaje C# (tipos primitivos, instrucciones y palabras clave) así como el desarrollo orientado a objetos. Controlará las novedades de esta versión (generic, iterator, partial class, nullable type, etc), un conjunto significativo de las clases del Framework que permiten la práctica de Threads, XML y del desarrollo de componentes. Al abordar tecnologías como el ADO.NET y los Servicios Web, el autor eligió deliberadamente ilustrar sus observaciones con esta otra vía abierta al desarrollador que representan los Smart Clients, alternativa a los ASP. NET. Esta elección permitirá al lector medir la contribución de las tecnologías ofrecidas por la arquitectura .NET siguiendo al mismo tiempo un planteamiento progresivo en el aprendizaje del lenguaje C#.
 

Nota: N

o hay un distribuidor en Sudamérica, con lo que la editorial recomienda dos opciones:

o hay un distribuidor en Sudamérica, con lo que la editorial recomienda dos opciones:

 
1 )cursar una solicitud de presupuesto a través de nuestra web (tras lo cual se cotizan los gastos de envío, y el cliente acepta o no el pedido)
2) comprarlo a través de Celesa, www.celesa.com

Clonación de objetos de estructura compleja


Introducción:
La asignación de una variable en otra, de tipos complejos, como son la mayoría de los objetos instanciados de clases del .NET Framework o clases desarrollados por nosotros, dan por resultado dos variables referenciando al mismo objeto. Este concepto es conocido en otros lenguajes de programación como punteros.


Siendo así que al modificar el atributo de un objeto apuntado por dos variables, veremos reflejados el cambio en ambas variables, ya que las dos apuntan a la misma instancia de la clase. Es decir el objeto vive en memoria una vez sola y tiene dos variables que apuntan a él. Por circunstancias de las reglas de negocio es necesario a veces obtener una copia en memoria de un objeto, teniendo así dos variables apuntando a 2 objetos distintos que contienen los mismos valores.


Solución:
El Framework .NET provee a todos los objetos un método llamado MemberwiseClone() que crea una copia simple del objeto. Una copia simple es una copia de los miembros de la clase sin realizar una copia de los objetos a los que estos miembros apuntan. ¿Que pasa entonces cuando queremos copiar obejtos de estructuras complejas que tiene atributos que contienen objetos que contienen atributos que contienen objetos y así sucesivamente? Se puede implementar la interfaz IClonable que soporta el método Clone(), para soportar explícitamente una copia profunda de la clase. De todas formas esto requiere de un trabajo de creación de objetos y asignación manual de valores que debe hacerse por líneas de código.  Esta tarea podía resultar muy ardua si la estructura del objeto a clonar es muy grande, y requiere una mantenimiento extra si la estructura de la clase se modifica.


Sería bueno también poder contar con algoritmo que nos permita ser reutilizado para todas las tareas de clonado de objetos. Es así que podemos recurrir a técnicas como Reflection que nos permita recursivamente inspeccionar y copiar los miembros del objeto y sus hijos.  Es una técnica aceptable la cual requiere de un poco de tiempo de procesamiento para realizarse, la cual podría adoptarse en aplicaciones que no son de misión crítica.


Como todos los tipos  que desarrollamos en.NET son serializables, podemos usar serialización de objetos para clonarlos. A continuación veremos un ejemplo donde utilizamos la técnica de seralización de un objeto en un espacio de memoria adicional o MemoryStream, y creamos una copia del objeto deserializandolo en una nueva instancia.


Desarrollo del problema:
Definición de la clase Cuadrado que contiene una colección de Puntos, la clonación de este objeto complejo no podrías hacerse con la técnica MemberwiseClone().


using System;
using System.Collections.Generic;
using System.Text;

namespace
CopiaObjetos
{
    [Serializable]
 
   class Punto
    {
        public int Y;
        public int X;


        public Punto(int x, int y)
        {
            X = x;
            Y = y;
        }
    }


    [Serializable]
    class Cuadrado : ICloneable 
    {
        public string Color;
        public string Textura;
        public Punto Centro;
        public List<Punto> Puntos;       


        public Cuadrado()
        {
            Puntos = new List<Punto>();
            Centro = new Punto(0,0);
        }


        public object Clone()
        {
            return Copiadora.Copiar(this);
        }
    }
}


Clonación profunda del objeto Cuadrado usando la técnica de seralización y deserialización en memoria.


using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
 


namespace CopiaObjetos
{
    class Program
    {
        static void Main(string[] args)
        {
            Cuadrado cuadrado = new Cuadrado();
            cuadrado.Color = “Rojo”;
            cuadrado.Textura = “Rugosa”;
            cuadrado.Centro.Y = 10;
            cuadrado.Centro.X = 10;
            cuadrado.Puntos.Add(new Punto(5, 5));
            cuadrado.Puntos.Add(new Punto(15, 5));
            cuadrado.Puntos.Add(new Punto(15, 15));
            cuadrado.Puntos.Add(new Punto(5,15));
            // Copia de objeto por referencia
            Cuadrado copiaCuadrada = cuadrado;

            //Al cambiar el color en el objeto original, vemos el cambio en la copia
            cuadrado.Color = “Verde”;
            Console.WriteLine(“————— Color Original Modificado ————“);
            Console.WriteLine(“Color: {0}”, cuadrado.Color);
            Console.WriteLine(“————— Color del Cuadrado Copiado por Referencia ————“);
            Console.WriteLine(“Color: {0}”, copiaCuadrada.Color);

            //Copia de objeto por clonación
            copiaCuadrada = cuadrado.Clone() as Cuadrado;


            //Inspeccionamos profundamente el objeto clonado
            Console.WriteLine(“————— Copia del cuadrado ————“);
            Console.WriteLine(“Color: {0}”, copiaCuadrada.Color);
            Console.WriteLine(“Textura: {0}”, copiaCuadrada.Textura);
            Console.WriteLine(“Centro: [{0},{1}]”, copiaCuadrada.Centro.X, copiaCuadrada.Centro.Y);
            Console.WriteLine(“Abajo Izquierda: [{0},{1}]”, copiaCuadrada.Puntos[0].X, copiaCuadrada.Puntos[0].Y);
            Console.WriteLine(“Abajo Derecha: [{0},{1}]”, copiaCuadrada.Puntos[1].X, copiaCuadrada.Puntos[1].Y);
            Console.WriteLine(“Arriba Derecha: [{0},{1}]”, copiaCuadrada.Puntos[2].X, copiaCuadrada.Puntos[2].Y);
            Console.WriteLine(“Arriba Izquierda: [{0},{1}]”, copiaCuadrada.Puntos[3].X, copiaCuadrada.Puntos[3].Y);
            //Modificamos el color del objeto original
            Console.WriteLine(“————— Color Original Modificado ————“);
            cuadrado.Color = “Azul”;
            Console.WriteLine(“Color: {0}”, cuadrado.Color);
            //Observamos que el valor del objeto cloando no se ha modificado
            Console.WriteLine(“————— Color del Cuadrado Copiado ————“);
            Console.WriteLine(“Color: {0}”, copiaCuadrada.Color);
            Console.ReadLine();
        }
    }

    /// <summary>
    /// Realiza una clonación de un objeto de estructura compleja
    /// </summary>
    public static class Copiadora
    {
        public static T Copiar<T>(T fuente)
        {
            //Verificamos que sea serializable antes de hacer la copia
            if (!typeof(T).IsSerializable)
            {
                throw new ArgumentException(“El tipo de dato debe ser serializable.”, “fuente”);
            }
            if (Object.ReferenceEquals(fuente, null))
            {
                return default(T);
            }
            //Creamos un stream en memoria
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();
            using (stream)
            {
                formatter.Serialize(stream, fuente);
                stream.Seek(0, SeekOrigin.Begin);
                //Deserializamos la porción de memoria en el nuevo objeto
                return (T)formatter.Deserialize(stream);
            }
        }
    }
}


Descargar código fuente 


Conclusión:
La ventaja de esta técnica es que nos provee un mecanismo rápido, sencillo y reutilizable para la clonación de objetos simples o estructuras de objetos complejas.


Este artículo fue publicado originalmente en la revista MTJ.NET de MSDN Latinoamérica en Mayo del 2006

digg_url = ‘http://msmvps.com/blogs/cwalzer’;
digg_bgcolor = ‘#ff9900’;
digg_skin = ‘compact’;
digg_window = ‘new’;

Agregar a Technorati

Mis Libros

Pro MSMQ: Microsoft Message Queue Programming



This book explores MSMQ so that you can initiate robust, asynchronous communication between applications. MSMQ provides three APIs to incorporate message queuing into different applications. These APIs include C from unmanaged C/C++ code; a COM component from VB or C++ code; and the System.Messaging namespace, which integrates MSMQ with managed C# or VB .NET applications.
This is the only book on the market to cover all three APIs. Plus, this book discusses the newest features of MSMQ 3.0 (released with Windows Server 2003), and explains sending and receiving MSMQ messages on a PocketPC device.
June 1, 2004


Reviews:
CodeGuru
Amazon


C#: Desarrollo con Visual Studio 2005


 


Este libro se dirige a desarrolladores, incluso principiantes, que quieren dominar el lenguaje C# (Visual C#). El lector descubrirá la plataforma de desarrollo Visual Studio 2005, las bases del lenguaje C# (tipos primitivos, instrucciones y palabras clave) así como el desarrollo orientado a objetos. Controlará las novedades de esta versión (generic, iterator, partial class, nullable type, etc), un conjunto significativo de las clases del Framework que permiten la práctica de Threads, XML y del desarrollo de componentes. Al abordar tecnologías como el ADO.NET y los Servicios Web, el autor eligió deliberadamente ilustrar sus observaciones con esta otra vía abierta al desarrollador que representan los Smart Clients, alternativa a los ASP. NET. Esta elección permitirá al lector medir la contribución de las tecnologías ofrecidas por la arquitectura .NET siguiendo al mismo tiempo un planteamiento progresivo en el aprendizaje del lenguaje C#..
Enero, 2008


Windows Vista Business
Practique la instalación, configuración y administración de su Sistema


 


Este libro está orientado a un público de informáticos o usuarios que ya tienen conocimientos generales sobre el uso de puestos de trabajo con Windows Vista. Los ejercicios le permitirán practicas: la instalación y la configuración del sistema Windows Vista, la creación y la administración de cuentas de usuarios, la administración de conexiones de red, la administración del conjunto del hardware (discos, impresoras, etc.). Igualmente, gracias al uso de diferentes herramientas, podrá probar el buen funcionamiento de Windows Vista.
Marzo, 2008


Using Modal Dialog Boxes in ASP.NET Applications



If you know that your end users are running Windows, it can be very useful to give your web applications a familiar Win32 app behavior. Using modal dialog boxes can in some cases provide your users with an intuitive interface and make site navigation easier. In this article, author Carlos Walzer demonstrates two techniques using Internet Explorer 5.0 and ASP.NET to implement this. The first technique uses the XMLHTTPRequest object included in the Microsoft XML 3.0 parser component, which provides client-side protocol support for communication with HTTP servers. The second technique enables Smart Navigation for your modal web forms. Walzer explores the details of both techniques and compares the advantages and disadvantages of each.


Building a Generic Report Engine Using SQL Server 2000, XML, and XSLT in ASP.NET



Explains how to create a generic aspx page to add reporting capabilities to an ASP.NET site. He demonstrates how this can be done by taking advantage of the set of classes introduced by .NET to manage XML, as well as the SQL Server 2000 XML features. The reporting aspx page created here is the result of combining System.Xml.XmlTextReader, XSLT, streams, and stored procedures that return XML using the FOR XML clause.


Sending Messages Through HTTP with MSMQ 3.0



Explores two important concepts involving Microsoft Message Queue 3.0: Direct Messaging and the support for referencing queues and formatting messages through the HTTP protocol. Throughout the article, Walzer thoroughly introduces and explains these topics while leading you through a development example that will quickly bring you up to speed on the technology.