jueves, 17 de mayo de 2012

Una forma distinta de ver las horas

Enlace

Fichero de Log Asíncrono

Hablando con algunos compañeros de trabajo, estábamos debatiendo sobre emplear ficheros de log. Soy firme defensor de ello, porque ante un error en producción, hay que conocer el porqué del fallo. El problema que nos encontrábamos era que al hacer uso de ficheros de log, la fvelocidad, disminuía muchísmo. así que buscando un poco he pensado que una buena solución es generar los ficheros de log de forma asíncrona. Se emplean las EnterPriseLibrary, porque para qué reinventar la rueda, por lo tanto no hay que olvidar la .dll.

using Microsoft.Practices.EnterpriseLibrary.Logging;

namespace ClassLibrary1
{
    public class Log
    {
        delegate void WriteLogDelegate(string message);

        public static void WriteLog(string message)
        {
            WriteLogDelegate logDelegate = new WriteLogDelegate(AsyncWriteLog);
            AsyncHelper.FireAndForget(logDelegate, message);
        }

        static void AsyncWriteLog(string message)
        {
            LogEntry log = new LogEntry();
            log.Message = message;

            Logger.Write(log);
        }      
      
    }
}
using System;

namespace ClassLibrary1
{
    /// <summary>
    /// This is asynchronous helper class from Jon Skeet
    /// http://www.yoda.arachsys.com/csharp/threads/threadpool.shtml
    /// </summary>
    public class AsyncHelper
    {
        /// <summary>
        /// Delegate to wrap another delegate and its arguments
        /// </summary>
        delegate void DelegateWrapper(Delegate d, object[] args);

        /// <summary>
        /// An instance of DelegateWrapper which calls InvokeWrappedDelegate,
        /// which in turn calls the DynamicInvoke method of the wrapped
        /// delegate.
        /// </summary>
        static DelegateWrapper wrapperInstance = new DelegateWrapper(InvokeWrappedDelegate);

        /// <summary>
        /// Callback used to call <code>EndInvoke</code> on the asynchronously
        /// invoked DelegateWrapper.
        /// </summary>
        static AsyncCallback callback = new AsyncCallback(EndWrapperInvoke);

        /// <summary>
        /// Executes the specified delegate with the specified arguments
        /// asynchronously on a thread pool thread.
        /// </summary>
        public static void FireAndForget(Delegate d, params object[] args)
        {
            // Invoke the wrapper asynchronously, which will then
            // execute the wrapped delegate synchronously (in the
            // thread pool thread)
            wrapperInstance.BeginInvoke(d, args, callback, null);
        }

        /// <summary>
        /// Invokes the wrapped delegate synchronously
        /// </summary>
        static void InvokeWrappedDelegate(Delegate d, object[] args)
        {
            d.DynamicInvoke(args);
        }

        /// <summary>
        /// Calls EndInvoke on the wrapper and Close on the resulting WaitHandle
        /// to prevent resource leaks.
        /// </summary>
        static void EndWrapperInvoke(IAsyncResult ar)
        {
            try
            {
                wrapperInstance.EndInvoke(ar);
                ar.AsyncWaitHandle.Close();
            }
            catch (Exception ex)
            {
                //Handle the exception.
            }
        }
    }
}


También hay que crear un fichero de configuración, que en este caso se llama: App.config y el contenido es:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  </configSections>
  <loggingConfiguration name="Logging Application Block" tracingEnabled="true"
    defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
    <listeners>
      <add fileName="SVPBuildTool.log" rollSizeKB="0" timeStampPattern="yyyy-MM-dd"
        rollFileExistsBehavior="Increment" rollInterval="Day" formatter="Text Formatter"
        header="----------------------------------------" footer="----------------------------------------"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
        traceOutputOptions="None" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
        name="Rolling Flat File Trace Listener" />
    </listeners>
    <formatters>
      <add template="Timestamp: {timestamp}&#xD;&#xA;Message: {message}&#xD;&#xA;Category: {category}&#xD;&#xA;Priority: {priority}&#xD;&#xA;EventId: {eventid}&#xD;&#xA;Severity: {severity}&#xD;&#xA;Title:{title}&#xD;&#xA;Machine: {machine}&#xD;&#xA;Application Domain: {appDomain}&#xD;&#xA;Process Id: {processId}&#xD;&#xA;Process Name: {processName}&#xD;&#xA;Win32 Thread Id: {win32ThreadId}&#xD;&#xA;Thread Name: {threadName}&#xD;&#xA;Extended Properties: {dictionary({key} - {value}&#xD;&#xA;)}"
        type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
        name="Text Formatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="General">
        <listeners>
          <add name="Rolling Flat File Trace Listener" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events">
        <listeners>
          <add name="Rolling Flat File Trace Listener" />
        </listeners>
      </allEvents>
      <notProcessed switchValue="All" name="Unprocessed Category" />
      <errors switchValue="All" name="Logging Errors &amp; Warnings" />
    </specialSources>
  </loggingConfiguration>
</configuration>

miércoles, 16 de mayo de 2012

Ejercicios para mejorar como programador

Code Chef es una página en la que se proponen ejercicios para que el programador mejore su forma de hacer las cosas.

viernes, 11 de mayo de 2012

Impress.js

Leyendo cosas de Fernando Blat (hace algunos años que le voy siguiendo la pista), me he encontrado con la librería para hacer presentaciones en la web. Cada vez estoy más impresionado.

He probado la página de demo y me he encontrado una grata sorpresa al ver su código fuente. Tengo que reconocer que soy de los que mira el código fuente de las páginas, para darme cuenta de todo lo que me queda.

Con unas cuantas cosas, se pueden hacer maravillas. La recomiendo muy fervientemente.

miércoles, 9 de mayo de 2012

Marshalling

 public static int? ToNullInt(string t)
    {
        int i = 0;
        if (int.TryParse(t, out i))
        {
            return i;
        }
        else
        {
            return null;
        }
    }
    public static short? ToNullShort(string t)
    {
        short i = 0;
        if (short.TryParse(t, out i))
        {
            return i;
        }
        else
        {
            return null;
        }
    }
    public static DateTime? ToNullDate(string t)
    {
        DateTime d = new DateTime();
        if (DateTime.TryParse(t, out d))
        {
            return d;
        }
        else
        {
            return null;
        }
    }
    public static decimal? ToNullDecimal(string t)
    {
        decimal d = 0;
        if (decimal.TryParse(t, out d))
        {
            return d;
        }
        else
        {
            return null;
        }
    }
    public static byte? ToNullByte(string t)
    {
        byte d = 0;
        if (byte.TryParse(t, out d))
        {
            return d;
        }
        else
        {
            return null;
        }
    }
    public static bool? ToNullBool(string t)
    {
        bool d = false;
        if (bool.TryParse(t, out d))
        {
            return d;
        }
        else
        {
            return null;
        }
    }
    public static string ToNullString(string t)
    {
        if (!string.IsNullOrEmpty(t))
        {
            return t;
        }
        else
        {
            return null;
        }
    }
    public static object ToNullValue(PropertyInfo propiedadDestino, PropertyInfo propiedadOrigen, Object objeto)
    {
        if (propiedadDestino.PropertyType == typeof(DateTime)
        || propiedadDestino.PropertyType == typeof(DateTime?))
        {
            return ToNullDate(propiedadOrigen.GetValue(objeto, null).ToString());
        }
        else if (propiedadDestino.PropertyType == typeof(int)
        || propiedadDestino.PropertyType == typeof(int?))
        {
            return ToNullInt(propiedadOrigen.GetValue(objeto, null).ToString());
        }
        else if (propiedadDestino.PropertyType == typeof(Int16)
        || propiedadDestino.PropertyType == typeof(Int16?))
        {
            return ToNullShort(propiedadOrigen.GetValue(objeto, null).ToString());
        }
        else if (propiedadDestino.PropertyType == typeof(decimal)
        || propiedadDestino.PropertyType == typeof(decimal?))
        {
            return ToNullDecimal(propiedadOrigen.GetValue(objeto, null).ToString());
        }
        else if (propiedadDestino.PropertyType == typeof(byte)
        || propiedadDestino.PropertyType == typeof(byte?))
        {
            return ToNullByte(propiedadOrigen.GetValue(objeto, null).ToString());
        }
        else if (propiedadDestino.PropertyType == typeof(bool)
        || propiedadDestino.PropertyType == typeof(bool?))
        {
            return ToNullBool(propiedadOrigen.GetValue(objeto, null).ToString());
        }
        else if (propiedadDestino.PropertyType == typeof(string))
        {
            object value = propiedadOrigen.GetValue(objeto, null);
            if (((string)value) == "") value = null;
            return value;
        }
        else
        {
            return propiedadOrigen.GetValue(objeto, null);
        }
    }
    public static Control GetControl(string id, Control contenedor)
    {
        Control control = contenedor.FindControl(id);
        if (control != null) return control;
        if (contenedor.Controls.Count != 0)
        {
            foreach (Control c in contenedor.Controls)
            {
                control = GetControl(id, c);
                if (control != null) return control;
            }
        }
        return null;
    }
    public static object FillObject(Control controlPadre, Type type, string prefijoIdControl)
    {
        //Crea un objeto del tipo dado
        object entity = Activator.CreateInstance(type);

        // Para cada propiedad del objeto
        foreach (PropertyInfo propiedad in type.GetProperties())
        {
            if (propiedad.CanWrite)
            {
                //Busca un control con id igual a "rep_" mas el nombre de la propiedad
                string idControl = string.Format("{0}{1}", prefijoIdControl, propiedad.Name);
                Control control = GetControl(idControl, controlPadre);

                //Si el control existe
                if (control != null)
                {
                    // Segun el tipo del control necesitamos una propiedad concreta
                    string nombrePropieda = "";
                    if (control is Ext.Net.CheckColumn) nombrePropieda = "Checked";
                    else if (control is Ext.Net.Hidden) nombrePropieda = "Value";
                    else if (control is Ext.Net.ComboBox) nombrePropieda = "SelectedValue";
                    else nombrePropieda = "Text";

                    // Recuperamos la propiedad del control que vamos a leer
                    PropertyInfo propiedadControl = control.GetType().GetProperty(nombrePropieda);

                    // Si la propiedad esta disponible
                    if (propiedadControl != null && propiedadControl.CanRead)
                    {
                        propiedad.SetValue(entity, ToNullValue(propiedad, propiedadControl, control), null);
                    }
                }
            }
        }
        return entity;
    }
    public static bool IsNullObject(object obj)
    {
        object propiedadControl;
        bool resultado = true;

        // Para cada propiedad del objeto
        foreach (PropertyInfo propiedad in obj.GetType().GetProperties())
        {
            if ((null != propiedad) && (propiedad.CanRead))
            {
                // Recuperamos la propiedad del control que vamos a leer
                propiedadControl = propiedad.GetValue(obj, null);
                if ((null != propiedadControl) &&
                    (false == propiedadControl.ToString().Contains("List"))) //No se toma en cuenta las listas --> IList
                {
                    resultado = false;
                    break;
                }

            }
        }
        return resultado;
    }
    public static void FillControl<t>(Control controlPadre, t entity)
    {
        FillControl(controlPadre, entity, "");
    }
    public static void FillControl<t>(Control controlPadre, t entity, string prefijoIdControl)
    {

        // Para cada propiedad del objeto
        foreach (PropertyInfo propiedad in entity.GetType().GetProperties())
        {
            if (propiedad.CanRead)
            {
                //Busca un control con id igual a "rep_" mas el nombre de la propiedad
                string idControl = string.Format("{0}{1}", prefijoIdControl, propiedad.Name);
                Control control = GetControl(idControl, controlPadre);

                //Si el control existe
                if (control != null)
                {
                    // Segun el tipo del control necesitamos una propiedad concreta
                    string nombrePropieda = "";
                    if (control is CheckColumn) nombrePropieda = "Checked";
                    else if (control is Hidden) nombrePropieda = "Value";
                    else if (control is ComboBox) nombrePropieda = "SelectedValue";
                    else if (control is Image) nombrePropieda = "ImageUrl";
                    else nombrePropieda = "Text";

                    // Recuperamos la propiedad del control que vamos a leer
                    PropertyInfo propiedadControl = control.GetType().GetProperty(nombrePropieda);

                    // Si la propiedad esta disponible
                    if (propiedadControl != null)
                    {
                        object value = propiedad.GetValue(entity, null);
                        //porque el setvalue, da problemas con el tipo boolean
                        if ((value != null) && (value.GetType() != typeof(Boolean)))
                            propiedadControl.SetValue(control, value.ToString(), null);
                        else
                            propiedadControl.SetValue(control, value, null);
                    }
                }
            }
        }
    }
    public static void ClearControl<t>(Control controlPadre, t entity, string prefijoIdControl)
    {
        // Para cada propiedad del objeto
        foreach (PropertyInfo propiedad in entity.GetType().GetProperties())
        {
            if (propiedad.CanRead)
            {
                //Busca un control con id igual a "rep_" mas el nombre de la propiedad
                string idControl = string.Format("{0}{1}", prefijoIdControl, propiedad.Name);
                Control control = GetControl(idControl, controlPadre);

                //Si el control existe
                if (control != null)
                {
                    // Segun el tipo del control necesitamos una propiedad concreta
                    string nombrePropieda = "";
                    if (control is CheckColumn) nombrePropieda = "Checked";
                    else if (control is Hidden) nombrePropieda = "Value";
                    else if (control is ComboBox) nombrePropieda = "SelectedValue";
                    else if (control is Image) nombrePropieda = "ImageUrl";
                    else nombrePropieda = "Text";

                    // Recuperamos la propiedad del control que vamos a leer
                    PropertyInfo propiedadControl = control.GetType().GetProperty(nombrePropieda);

                    // Si la propiedad esta disponible
                    if (propiedadControl != null)
                    {
                        propiedadControl.SetValue(control, null, null);
                    }
                }
            }
        }
    }

Videos sobre TDD

Navegando (que raro), me he encontrado esta serie de videos sobre TDD

Trabajos

Los mejores 25 trabajos.