Gestión de excepciones en c#

La gestión de excepciones es un punto siempre importante para garantizar que una aplicación se comporta de manera adecuada ante situaciones inesperadas.

Aquí tenéis una implementación de un “framework” muy simple, pero extensible, que nos permitirá normalizar la gestión de las excepciones en nuestro sistema.

La clase Work<T>:

public class Work<T>

{
private readonly Func<Task<T>> task;
private readonly ExceptionHandler exceptionHandler;

public Work(Func<Task<T>> task)
: this(task, new NoExceptionHandler())
{ }

public Work(
Func<Task<T>> task,
ExceptionHandler handler)
{
this.task = task;
exceptionHandler = handler;
}

public async Task<Result<T>> Run()
{
try
{
var result = await task();
return Ok(result);
}
catch (Exception ex)
{
exceptionHandler.Handle(ex);
return Error();
}
}
}

Nos permitirá ejecutar tareas asíncronas y gestionar las posibles excepciones que puedan ocurrir. Además, aprovechando el uso del patrón decorador con la interface ExceptionHandler, podremos personalizar el comportamiento de nuestro código cuando se de alguna excepción.

Incluso podemos crear un handler para gestionar esas típicas excepciones comunes que tenemos en nuestro proyecto y que repetimos una y otra vez por todos lados.

Aquí tenéis el código con tests y todo 🙂

https://github.com/juanlao/ExceptionHandlingLibrary

Espero que os sirva

Cómo encontrar la versión de MSBuild que está instalada

Recientemente me ha sido necesario averiguar cual es la última versión de MSBuild que está instalada en el sistema. Hacer la comprobación de que existe un archivo en el path por defecto del tipo “C:Program Files (x86)Microsoft Visual Studio2017CommunityMSBuild15.0Bin” no es buena idea. Ya que por ejemplo puede que el usuario no lo haya instalado en ese directorio,

En StackOverflow tenéis una solución bastante interesante.

Los pasos:

  1. Instalar el paquete de Nuget Microsoft.Build.Framework.
  2. Las versiones 4.0, 12.0 y 14.0 dejan una entrada en el registro con el path:
      • Podemos consultarla
    Registry.LocalMachine.OpenSubKey($@"SOFTWAREMicrosoftMSBuildToolsVersions{msBuildVersion}")
    
  3. Para la última versión, la 15.0 hay que hacer algo más ya que esta última versión no deja huella en el registro.
    • Es necesario añadir el paquete Nuget: Microsoft.VisualStudio.Setup.Configuration.Interop
    • Y con este código es posible buscar en dónde está:
 var query = new SetupConfiguration();

<pre><code>    var query2 = (ISetupConfiguration2)query;

    var e = query2.EnumAllInstances();

    var helper = (ISetupHelper)query;

    int fetched;

    var instances = new ISetupInstance[1];

    do
    {
        e.Next(1, instances, out fetched);
        if (fetched &amp;gt; 0)
        {
            var instance = instances[0];

            var instance2 = (ISetupInstance2)instance;

            var state = instance2.GetState();

            // Skip non-complete instance, I guess?
            // Skip non-local instance, I guess?
            // Skip unregistered products?
            if (state != InstanceState.Complete
                || (state &amp;amp; InstanceState.Local) != InstanceState.Local
                || (state &amp;amp; InstanceState.Registered) != InstanceState.Registered)
            {
                continue;
            }

            var msBuildComponent =
                instance2.GetPackages()
                    .FirstOrDefault(
                        p =&amp;gt;
                            p.GetId()
                                .Equals(&amp;quot;Microsoft.Component.MSBuild&amp;quot;,
                                    StringComparison.InvariantCultureIgnoreCase));

            if (msBuildComponent == null)
            {
                continue;
            }

            var instanceRootDirectory = instance2.GetInstallationPath();

            var msbuildPathInInstance = Path.Combine(instanceRootDirectory, &amp;quot;MSBuild&amp;quot;, msBuildVersion, &amp;quot;Bin&amp;quot;, &amp;quot;msbuild.exe&amp;quot;);

            if (File.Exists(msbuildPathInInstance))
            {
                return msbuildPathInInstance;
            }
        }
    } while (fetched &amp;gt; 0);
</code></pre>

Jugando con este código ya podemos ver de una forma más adecuada dónde están instaladas las versiones de MSBuild.

Espero que os sirva.

Post original en StackOverflow

 

Modificar el valor de un struct con Reflection

He estado trabajando con nuestro amigo @jacano, conocido por todos como ReflectorMan, y nos ha sido necesario modificar por reflexión el valor de una estructura (struct).

De todas las formas que encontramos de hacerlo, vimos que la más sensata es:

object boxedObject = myStruct;

….

Info.SetValue(boxedObject, structValue);

…

myStruct = (MyStruct)boxedObject;

El truco está en que al hacer el casting a object, estamos haciendo un boxing de la estructura, es decir, lo estamos convirtiendo en objecto, y podemos pasarselo al método SetValue(). Ya que todos sabemos que las estructuras se pasan por valor.

Y justo después casteamos ese objeto al tipo de la estructura para hacer el unbox y quedarnos con el valor de la estructura.

Espero que os resulte útil.

El foreach puede causar problemas de memoria

Después de tener algo de tiempo he ido a mi lista de cosas por leer y me quedado a cuadros cuando lo he leído.

http://blogs.msdn.com/b/etayrien/archive/2007/03/17/foreach-garbage-and-the-clr-profiler.aspx

Sí es un enlace del 2007, lo sé, imaginaos la de cosas que tengo en esa lista :P.

En resumen, imaginemos este código:


class Program
{
    class GameEntity
    {
        public void Update()
        {
        }
    }

<pre><code>static GameEntity[] entities = new GameEntity[100];
static Program()
{
    for (int i = 0; i &amp;lt; entities.Length; i++)
    {
        entities[i] = new GameEntity();
    }
}

static void Main(string[] args)
{
    byte[] byteArray = new byte[1];
    for (int i = 0; i &amp;lt; entities.Length; i++)
    {
        entities[i].Update();
    }
}
</code></pre>

}

En el post original, después de pasar el CLR Profiler no se hace reserva de memoria para un enumerador para poder recorrer la colección, algo lógico. Después, para ver la diferencia con el foreach sustituye el código del for por este otro:

static void Main(string[] args)
{
   byte[] byteArray = new byte[1];
   foreach (GameEntity e in entities)
   {
      e.Update();
   }
}

En el caso del foreach se reserva memoria para un enumerador necesario para recorrer el foreach.

Y todo va perfecto, sin embargo, hay un escenario en el que se pueden producir fugas de memoria:

const int NumEntities = 100;

static List list = new List();
static Program()
{
   for (int i = 0; i < NumEntities; i++)
   {
         list.Add(new GameEntity());
     }
}
static void Main(string[] args)
 {
     UpdateIEnumerable(list);
 }
private static void UpdateIEnumerable(IEnumerable enumerable)
 {
     foreach (GameEntity e in enumerable)
     {
         e.Update();
     }
 }

En este caso sí se producen fugas de memoria. Y es que aunque estemos haciendo un foreach en una lista, cuando se le hace un casting a una interfaz, al tipo valor del enumerador se le hace un box, y se coloca en el heap.

La conclusión:

  • Cuando hacemos un foreach sobre un Collection<T> se reserva memoria para un enumerador.
  • Cuando hacemos un foreach sobre la mayoría de las colecciones, como arrays, listas, colas, listas enlazadas y otras:
    • Si se usan explícitamente, NO se reserva memoria para un enumerador.
    • Si se usan a través de interfaces, se reserva memoria para un enumerador.

Así que si el consumo de memoria es algo crítico en vuestra aplicación o juego , nunca, nunca, uséis interfaces para recorrer una colección.

 

[Update: Gracias a Bernardo por el comentario]

El problema aparece cuando el “foreach” recorre la colección como si fuera un “IEnumerable”. En este caso se utiliza la implementación explícita de “GetEnumerator()” y se realiza “boxing” del “struct” para devolver un tipo “IEnumerator”.

El “boxing” es una operación costosa y puede llegar a consumir mucha memoria.

P.D: el método “GetEnumerator()” de  “Collection” no devuelve un “struct”. Es de las pocas colecciones que son una excepción.

Espero que os haya gustado tanto como a mi. 🙂

Juan María Laó Ramos.

CodeFluent Entities. Nunca el DDD fué tan fácil

Vamos a ver en este post es un producto que he encontrado y parece muy prometedor. CodeFluent Entities es una herramienta de modelado que nos permite generar y mantener actualizadas todas las layers y capas de nuestra aplicación. Asegurando el conjunto de buenas prácticas arquitecturales en nuestros sistemas desde su nacimiento. Esto es, han creado una herramienta para aplicar Domain Driven Development sin que apenas nos demos cuenta.

La he estado probando un tiempo y la verdad me ha dejado sorprendido, pensé en un momento que iba a ser un ORM más, pero luego descubrí el modelador de objetos de negocio, seguido de la generación de servicios RESTful, la sencillez de enlazar el modelo de negocio con las interfaces de usuario ASP.NET Web Forms, WPF y Windows Forms (están trabajando en los conectores para ASP.NET MVC, Silverlight). Continue reading “CodeFluent Entities. Nunca el DDD fué tan fácil”

¿Que significa que mi programa termine con el mensaje “This application has requested the runtime to terminate it in an unusual way”?

Estamos ejecutando nuestro programa, y de repente sale el mensaje “This application has requested Runtime to terminate in an unusual way”. ¿Que ha pasado?
El mensaje lo imprime la función abort del runtime de C.
Un programa puede llamar a abort explícitamente, o puede ser llamado por el runtime.
  • La macro assert llama a abort cuando ocurre una aserción.
  • Por defecto, la función terminate llama a abort.

El estándar de C++ indica las condiciones bajo las que se llama a terminate, es una lista muy larga y no vamos a repetirla aquí. Para ver esa lista consulta tu copia favorita de estándares de C++ para verla. (la razón más común para este problema es que se ha lanzado una excepción y no se ha capturado).

Espero que sirva.
Juan María Laó Ramos.

El Señor de los Proyectos.

Durante la segunda edad del sol, los Mírdain (Altos Herreros Élficos) crearon diferentes plantillas de proyectos para Visual Studio. Estas plantillas tenían la particularidad de poseer grandes poderes imbuidos por sus creadores con el objetivo de hacer que la productividad de los desarrolladores fuera amplísima. Sin embargo los Mírdain fueron corrompidos por los Patrones de diseño, y crearon la plantilla PCL (Portable Class Library) cuyo objetivo es gobernarlos, encontrarlos, atraerlos a todos y atarlos en nuestros proyectos. Continue reading “El Señor de los Proyectos.”

Ejecutar Test unitarios en el modo MTA (Multiple Threaded Apartment)

¿Trabajas con TDD? ¿Haces test unitarios con MSTests? ¿Tienes una máquina con varias cpus?.

Sip, parece un mundo ideal sobre todo por lo de hacer TDD, ;). Sin embargo como los TDDadores son como las meigas … (existir no existen, pero haberlas haylas). Seguramente tendrán máquinas multicore y posiblemente haran test con Visual Studio 2010 y MSTests.

En este post veremos cómo podemos ejecutar nuestros test unitarios en el modo MTA (Multiple Threaded Apartment), lo que se conoce como hacer que se ejecuten en paralelo. Y es que el modo por defecto de su ejecución es el STA (Single threaded apartment). Continue reading “Ejecutar Test unitarios en el modo MTA (Multiple Threaded Apartment)”

Model Binding Parte 2: Filtrando datos (Serie ASP.NET vNext)

Este es el cuarto de una serie de post que estoy haciendo sobre ASP.NET vNext.

La próxima release de Visual Studio incluye un montón de nuevas características de edición de código (de las que hablaré también en el futuro). En el post de hoy veremos algunas pequeñas mejoras que incrementarán un montón la productividad con el editor de HTML a la hora de hacer las tareas más comunes.

Este post es el segundo de tres en el que hablamos sobre el nuevo soporte de Model Binding en Web Forms. Model Binding es una extensión del sistema de databinding de ASP.NET Web Forms , y ofrece un paradigma de acceso a datos centrados en el código. Hace uso de un montón de conceptos de binding que introdujimos con ASP.NET MVC – y los integra en el modelo de controles de servidor de Web Forms.

En el primer post de Model Binding vimos las bases sobre selección de datos. En el post de hoy vamos a ver cómo podemos filtrar datos previamente seleccionados basandose en la entrada de usuario, mientras mantenemos una visión de acceso a datos centrada en código. Veremos cómo podemos usar filtros con entrada de datos y valores obtenidos de un control dropdownlist. Continue reading “Model Binding Parte 2: Filtrando datos (Serie ASP.NET vNext)”

Design a site like this with WordPress.com
Get started