Blog de Francisco Velázquez

otro blog personal

Posts Tagged ‘c#

F# para desarrolladores de C#

leave a comment »

He estado viendo esta presentación: F# for C# developers de Øredev, que podría llamarse como agilizar las pruebas con F#. Ya que propone usar F# para facilitar las pruebas en aplicaciones que podrían estar desarrolladas en c#.

Aquí se puede ver como se define una clase:

fsharp_class_definition

Aquí como usar Nunit para hacer una prueba unitaria:

fsharp_unit_test

Sobre el min 30:39, podemos ver como hacer pruebas primero usando Fsunit y después unquote:

fsharp_unit_test_fsunit_unquote

Así mismo mostró como hacer BDD.

fsharp_bdd

Y por último como realizar Mocks:

fsharp_mocks_1

fsharp_mocks_2

Written by fravelgue

January 2, 2014 at 3:34 pm

Posted in development

Tagged with , ,

QueryString Helper

leave a comment »

Muy a menudo tengo que consultar los valores de las QueryStrings, y la verdad es que es horrible el montón de comprobaciones que hay que hacer. Además muchas veces, wap proxies o adsevers incluyen caracteres en la querystring, haciendo que los parsers lancen excepciones.

public static class Extensions
{
private static readonly Regex LeadingInteger = new Regex(@"^(-?\d+)");

public static T Get<T>(this System.Collections.Specialized.NameValueCollection nvc, string key)
where T : IConvertible
{
T obj = default(T);

if (nvc == null || string.IsNullOrEmpty(nvc[key]))
return default(T);

string v = nvc[key];

if (typeof(T) == typeof(Guid))
v = v.Substring(0, 36);

if (typeof(T) == typeof(int))
{   //http://stackoverflow.com/a/975512/22055
Match match = LeadingInteger.Match(v);
if (!match.Success)
v = match.Value;
else
return default(T);
}

try
{
obj = (T)Convert.ChangeType(v, typeof(T));
}
catch { }
return obj;
}
}

A veces, echo de menos las facilidades de lenguajes dinámicos como JS, por ejemplo, en el parseInt

Written by fravelgue

May 24, 2012 at 6:41 pm

Posted in development

Tagged with , ,

Helper para ConfigurationElementCollection

leave a comment »

Interesante utilidad que ayuda muchísimo para trabajar con colecciones en archivos de configuración.

    [ConfigurationCollection(typeof(ConfigurationElement))]
    public class ConfigurationElementCollection<T> :
        ConfigurationElementCollection, IEnumerable<T> where T : ConfigurationElement, new()
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new T();
        }
        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((T)(element)).ToString();
        }
        public T this[int idx]
        {
            get { return (T)BaseGet(idx); }
        }

        public new IEnumerator<T> GetEnumerator()
        {
            int count = base.Count;
            for (int i = 0; i < count; i++)
                yield return base.BaseGet(i) as T;
        }

Written by fravelgue

September 6, 2011 at 4:41 pm

Posted in development

Tagged with , , ,

Simple cache para BusinessObjects

leave a comment »

Debido a la naturaleza de mi trabajo, aplicaciones multitenant, y servicios M2M, para mejorar el rendimiento suelo cachear muchos objectos que tienen un tasa de lectura muy alta y de cambios muy muy pequeño. Así que para facilitar el trabajo, me he decido crear una pequeña utilidad.

    /// <summary>
    /// Concurrent cache for BusinessObject.  It doesn´t clean cache, useful for small data.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BusinessObjectCache<T>
        where T : BusinessObject<T>
    {
        static ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
        static volatile Dictionary<object, T> storage;

        static BusinessObjectCache()
        {
            Locker.EnterWriteLock();
            try
            {
                storage = new Dictionary<object, T>();
            }
            finally { Locker.ExitWriteLock(); }
        }

        public T Get(object id)
        {
            T o = null;
            Locker.EnterReadLock();
            try
            {
                if (storage.ContainsKey(id))
                {
                    o = storage[id];
                    return o;
                }
            }
            finally { Locker.ExitReadLock(); }

            if (o == null)
            {
                Locker.EnterUpgradeableReadLock();
                try
                {
                    if (!storage.ContainsKey(id))
                        o = BusinessObject<T>.Retrieve(id);

                    if (o != null)
                    {
                        Locker.EnterWriteLock();
                        try
                        {
                            storage[id] = o;
                        }
                        finally { Locker.ExitWriteLock(); }
                    }
                }
                finally { Locker.ExitUpgradeableReadLock(); }
            }

            return o;
        }
    }

A ver si me lo curro y la hago LRU.

Written by fravelgue

July 21, 2011 at 5:44 pm

Posted in development

Tagged with , ,

Simple HTTP GET en C#

leave a comment »

La verdad es que, a veces, cosas sencillas se hacen  complicadas en .NET y en mi opinión esta es una de ellas. Nada que objetar a que un framework tiene que ser lo menos restrictivo posible, pero en este caso no encuentro el sentido de que un error HTTP tenga que lanzar una excepción, yo personalmente la definiría como excepción vexing. Y bueno como estamos para ayudar pues con esta pequeña función todo será un poco más sencillo.

        public static int Get(string uri, int timeout, out string response)
        {
            int statusCode = -1;
            response = string.Empty;

            HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
            request.KeepAlive = false;
            request.Timeout = timeout;

            try
            {
                using (HttpWebResponse res = (HttpWebResponse)request.GetResponse() as HttpWebResponse)
                {
                    statusCode = (int)res.StatusCode;
                    using (Stream dataStream = res.GetResponseStream())
                    {
                        using (StreamReader reader = new StreamReader(dataStream))
                        {
                            response = reader.ReadToEnd();
                        }
                    }
                }
            }
            catch (WebException wex)
            {
                //http://msdn.microsoft.com/en-us/library/es54hw8e.aspx
                if (wex.Status == WebExceptionStatus.ProtocolError)
                {
                    // If status is WebExceptionStatus.ProtocolError,
                    // there has been a protocol error and a WebResponse
                    // should exist. Display the protocol error.
                    using (HttpWebResponse res = wex.Response as HttpWebResponse)
                    {
                        if (res != null)
                        {
                            statusCode = (int)res.StatusCode;

                            using (Stream s = wex.Response.GetResponseStream())
                            using (StreamReader reader = new StreamReader(s))
                            {
                                response = reader.ReadToEnd();
                            }
                        }
                        else
                        {   // no http status code available
                            throw wex;
                        }
                    }
                }
                else
                {   // no http status code available
                    throw wex;
                }
            }

            return statusCode;
        }

Cuanto más veo ese código, menos me gusta como está diseñado.
Un par de enlaces.

Written by fravelgue

July 19, 2011 at 7:27 pm

Posted in development

Tagged with , , , , ,

DAOs sobre Dapper

leave a comment »

La verdad es que los micro-ORMs están de moda (Massive, Dapper, PetaPOCO, SimpleData, etc). Basándome en esta abstracción y en mi querido Gentle.NET, me he decido a construir unos DAOs sobre Dapper, que es usado en Stackoverflow, y como características principales podemos decir: que es fuertemente tipado con una interfaz muy clara, y como extra soporta operaciones asíncronas a DB.

Creo que la mejor manera de entender el funcionamiento es con un ejemplo:

    class Example
    {
        class Message
            : BusinessObject<Message>
        {
            [PrimaryKey]
            public Guid Id { get; set; }
            public string DestinationAddress { get; set; }
            public string SourceAddress { get; set; }
            public string UserData { get; set; }
            public int Ton { get; set; }

        }

        public void Example1()
        {
            Message m = new Message()
            {
                Id = Guid.NewGuid(),
                DestinationAddress = "34612345678",
                SourceAddress = "404",
                UserData = "Example 01",
                Ton = 1
            };

            m.Insert();

            List<Message> l = Message.FindBy(new SqlCondition("DestinationAddress", Operator.Equals, "34612345678"));

            m.Remove();
        }
    }

A continuación mostraremos el código de las funciones básicas de CRUD.

    public class BusinessObject<T>
        where T: class
    {
        public static SqlConnection GetConnection()
        {
            return ConnectionFactory.Create(typeof(T).Namespace);
        }

        public static T Retrieve(object id)
        {
            string sql = string.Empty;
            DynamicParameters p = new DynamicParameters();
            p.Add(GetPrimaryKey(), id, null, null, null);
            StringBuilder sb = new StringBuilder()
                .AppendFormat("select * from {0} where {1} = @{1}", GetTableName(), GetPrimaryKey());
            return queryInternal(sb.ToString(), p).FirstOrDefault();
        }

        public void Insert()
        {
            string sql = string.Empty;
            DynamicParameters p = new DynamicParameters();
            StringBuilder columns = new StringBuilder(), values = new StringBuilder();
            bool first = true;

            foreach (string prop in GetProperties())
            {
                if (first)
                {
                    columns.AppendFormat("{0}", prop);
                    values.AppendFormat("@{0}", prop);
                }
                else
                {
                    columns.AppendFormat(", {0}", prop);
                    values.AppendFormat(", @{0}", prop);
                }
                p.Add(prop, getPropertyValue(this, prop), null, null, null);
                first = false;
            }

            sql = string.Format("insert into {0} ({1}) values ({2})",
                GetTableName(), columns.ToString(), values.ToString());

            int res = executeInternal(sql, p);
        }

        public void Update()
        {
            // ... 
        }
        public void Remove()
        {
            // ...
        }

        public static List<T> FindBy(SqlCondition[] conditions)
        {
            DynamicParameters p = new DynamicParameters();
            StringBuilder sb = new StringBuilder()
                .AppendFormat("select * from {0} where", typeof(T).Name);

            bool first = true;
            int i = 0;
            foreach (SqlCondition c in conditions)
            {
                // for multiple conditions with same column
                string var = c.PropertyName + (i++);
                if (!first) sb.Append(" AND");

                if (c.Value == null)
                {
                    sb.AppendFormat(" {0} {1} NULL", c.PropertyName, OperatorHelper.ToString(c.Operator));
                }
                else
                {
                    sb.AppendFormat(" {0} {1} @{2}", c.PropertyName, OperatorHelper.ToString(c.Operator), var);
                    p.Add(var, c.Value, null, null, null);
                }
                first = false;
            }

            return queryInternal(sb.ToString(), p);
        }

        protected static List<T> queryInternal(string sql, object param)
        {
            List<T> l = null;

            using (var conn = GetConnection())
            {
                try
                {
                    conn.Open();
                    l = conn.Query<T>(sql, param, null, false, 0, null).ToList();
                }
                finally { conn.Close(); }
            }

            return l;
        }

Faltaría algo de código para representar las condiciones SQL, así como algunas funciones que usan reflección para optener el nombre de la tabla, propiedades o clave primaria.

Written by fravelgue

June 27, 2011 at 8:11 pm

Posted in development

Tagged with , ,

Deserializar en C# ignorando DTD

leave a comment »

        public static object Deserialize(System.Type type, string data)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(type);
            TextReader textReader = new StringReader(data);
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ProhibitDtd = false;
            settings.XmlResolver = null;
            XmlReader xmlReader = XmlTextReader.Create(textReader, settings);
            return xmlSerializer.Deserialize(xmlReader);
        }

Written by fravelgue

June 8, 2011 at 9:48 am

Posted in development

Tagged with , , ,

Mini-ORMs

with one comment

Desde que se publicara Massive, que a mí personalmente me impresionó. Han aparecido algunos mini-orms, como PetaPoco o Dapper.Net (usado en stackoverflow). Realmente lo podríamos llamar la capa de acceso a datos tradicional, pero que con la nueva funcionalidad de C# todo es más fácil. Una evolución de AutoMapper.


public static List<T> AutoMap<T>(this IDataReader dr)
 where T : new()
 {
 Type businessEntityType = typeof(T);
 List<T> entitys = new List<T>();
 Hashtable hashtable = new Hashtable();
 PropertyInfo[] properties = businessEntityType.GetProperties();

 foreach (PropertyInfo info in properties)
 {
 hashtable[info.Name.ToUpper()] = info;
 }

 while (dr.Read())
 {
 T newObject = new T();
 for (int index = 0; index < dr.FieldCount; index++)
 {
 PropertyInfo info = (PropertyInfo)hashtable[dr.GetName(index).ToUpper()];
 if ((info != null) && info.CanWrite)
 {
 info.SetValue(newObject, dr.GetValue(index), null);
 }
 }
 entitys.Add(newObject);
 }
 dr.Close();
 return entitys;
 }

Creo que es esto es otra muestra del rechazo a la over-engineering.

Written by fravelgue

April 6, 2011 at 9:08 pm

Posted in development

Tagged with , ,

IIS7 Request no disponible en Application_Start

leave a comment »

Este estupendo cambio me ha producido una perdida de varias horas al pasar una aplicación a un servidor con IIS7. Por otro lado seré alguna vez capaz de usar la depuración remota.

Written by fravelgue

March 4, 2010 at 11:57 pm

Posted in development

Tagged with , , ,

Basic Authentication en HTTP Post

leave a comment »

string uri = string.Empty, user = string.Empty, password = string.Empty, postData = string.Empty, responseData = string.Empty;
            string encodedAuthorization = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(user + ":" + password));
HttpWebRequest webRequest = WebRequest.Create(uri) as HttpWebRequest;
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Headers = new WebHeaderCollection();
webRequest.Headers.Add("Authorization: Basic "+encodedAuthorization);

using (StreamWriter rw = new StreamWriter(webRequest.GetRequestStream()))
{
            rw.Write(postData);
}

using (StreamReader sr = new StreamReader(webRequest.GetResponse().GetResponseStream()))
{
            responseData = sr.ReadToEnd();
}

Written by fravelgue

February 10, 2010 at 10:58 pm

Posted in development

Tagged with , , , ,