TeraBIThia

21/05/08

Bug Visual Studio 2005 SDK

Archivado en: Uncategorized — crisfervil @ 8:16 am

 

[Image]

Me he encontrado con este problema.
Al compilar las soluciones, se incluye automáticamente la siguiente entrada en algunos archivos .csproj

<ItemGroup>
<Service Include="{B4F97281-0DBD-4835-9ED8-7DFB966E87FF}" />
</ItemGroup> 

Además, en los proyectos web se incluye también automáticamente el archivo vwd.webinfo

Tras investigar un poco, he visto que el problema lo origina la instalación del SDK de Visual Studio 2005.
Más concretamente, tras instalar el SDK no surge el problema, sino tras simplemente visualizar en el diálogo de opciones la rama de DSLTools/TextTemplating.

[Image]

Se soluciona eliminando las siguientes entradas del registro

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\Packages\{a9696de6-e209-414d-bbec-a0506fb0e924}HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0Exp\Packages\{a9696de6-e209-414d-bbec-a0506fb0e924} 

Fuentes:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=954064
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=274788&wa=wsignin1.0

Crossposted from crisfervil.com

19/05/08

Importancia de las pruebas

Archivado en: Uncategorized — crisfervil @ 9:13 am

Leo en esta entrada (http://blogs.msdn.com/tomholl/archive/2008/05/17/enterprise-library-4-0-get-it-while-it-s-hot.aspx) del blog de Tom Hollander, sobre las novedades de la versión 4.0 de la Enterprise Library.
Tom hace un agradecimiento al equipo de desarrollo de la EntLib y lo nombra:

- Product Management: Grigori Melnik
- Program Management: Scott Densmore, William Loeffler, Chris Tavares, and Grigori Melnik
- Architecture: Chris Tavares, Scott Densmore and Fernando Simonazzi
- Development: Chris Tavares, Fernando Simonazzi, and Nicolas Botto
- Test team: Hanz Zhang, Carlos Farre, Rohit Sharma, Naveen Guda, Pooja Parate, Pravin Pawar, Ronita Acharya, Sai Pasumarthi Venkata Appaji Sirangi and Vijaya Janakiraman
- Documentation: Alex Homer
- Edit team: Nelly Delgado, RoAnn Corbisier and Tina Burden McGrayne

Lo que más me ha llamado la atención es el siguiente dato: tres personas en el equipo de desarrollo y NUEVE en el de Testing. Ninguna de las personas del equipo de desarrollo participa en el de las pruebas.

Otro dato en este sentido : 8000 casos de prueba escritos para el proyecto.

Cada día lo tengo más claro, y estos datos no hacen más que afianzarme en mi convicción; las pruebas son el elemento que hacen que un proyecto de desarrollo tenga un resultado de calidad. Las pruebas exigen agregar más WorkItems en prácticamente todas las fases, y esto tiene un coste. Pero merece la pena.

Crossposted from crisfervil.com

16/05/08

Arguments Handler

Archivado en: General — crisfervil @ 11:34 pm

Llevo varios días queriendo escribir este post. La verdad es que cuando se escriben habitualmente aplicaciones de consola, tener que lidiar cada vez con la manera en que gestionamos los parámetros que admitimos en la línea de comandos es un poco engorroso.

Por eso, en su día escribí una función genérica que me ahorraba todo el trabajo.

Esta mañana, me encontré con este post de mi vecino virtual ;) . En él, Valeriano nos hace una propuesta para tratar los argumentos de la línea de comandos.

Yo quisiera pues, dar otro enfoque, que no es mejor ni peor, ya que que tiene por contra que es menos flexible y más complejo de implementar, pero me parece un poco más cómodo de usar.

A mí me gustaría poder definir una clase, que represente todos los parámetros que admite mi programa. Una propiedad por cada parámetro. Con su tipo correspondiente (esto me ahorraría validaciones sencillas). Si el tipo de la propiedad es un bool, lo trataremos como modificador.

Por ejemplo, para el comando

c:\ConsoleApplication9.exe FileName="c:\Program Files\Test.txt" Overwrite ShowProgress

Tenemos:
El parámetro FileName, con valor c:\Program Files\Test.txt
El parámetro Overwrite, que es un modificador.
El parámetro ShowProgress, que es un modificador.

Además, mi aplicación admitirá otros parámetros. Definiremos por lo tanto un clase que los contemple a todos.

image

 Command: Como la aplicación admite varios parámetros, establecemos una propiedad que nos indicará cuál ejecutar. Los parámetros admitidos vienen definidos en el Enum Commands. Pueden ser Get, Set y Delete.

FileName: Un string cualquiera.

Format: Otro Enum. En este caso para los formatos de salida del comando. Al igual que Command, se definen los valores posibles en un Enum.

Overwrite: Es un modificador. Es decir, no tiene valor. La presencia de este parámetro dentro de los argumentos se indicaría con un true en esta propiedad.

Password: Otro string cualquiera.

ShowProgress: Otro modificador. Igual que Overwrite.

StartDate: Un valor de tipo fecha. La propiedad debería ser un nullable, para que cuando no se haya especificado valor, lo podamos saber.

UserName: Otro string cualquiera.

Necesitaremos, una función que, a partir del array de string que recibimos en el Main, obtenga una instancia de MyArguments con todas las propiedades rellenas correctamente. Debería además ser genérica para no tener que andar realizando conversiones.

class Program
{
    static void Main(string[] args)
    {
        MyArguments myArgs = ArgumentsHandler.Get<MyArguments>(args);
    }
}

Y cómo se cocina esto?… pues, allá vamos.

En primer lugar, hemos de saber que cada elemento del parámetro args representa cada uno de los parámetros de la línea de comandos. Y cada parámetro viene delimitado por espacios en la cadena obtenida en System.Environment.CommandLine . Para incluir un espacio como parte de un parámetro debemos delimitarlo por comillas. Y los items de args no incluirán estas comillas.
Si tomamos como ejemplo la línea:

c:\ConsoleApplication9.exe FileName="c:\Program Files\Test.txt" Overwrite ShowProgress pepe juan

args[0] será igual a FileName=c:\Program Files\Test.txt
args[1] será igual a Overwrite
args[2] será igual a ShowProgress
args[3] será igual a pepe
args[4] será igual a juan

Como primer paso, crearemos la clase ArgumentsHandler con un método estático Get, que además sea genérico. Este método admitirá el array de string que contendrá los parámertros recibidos en el Main.

public class ArgumentsHandler
{
    public static T Get<T>(string[] args) where T : new()
    {
    }
}

Necesitamos una manera de obtener la referencia a una propiedad de T, a partir del nombre. No tendremos en cuenta las mayúsculas/minúsculas. Lo haremos por reflexión. La propiedad debe ser pública y ser una propiedad de instancia (no estática).

private static PropertyInfo GetPropertyInfo(string propertyName, Type argumentsEntityType)
{
    PropertyInfo retVal = null;
    retVal = argumentsEntityType.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
    return retVal;
}

Si propertyName no es propiedad de T, este método devolverá null. Pero qué haremos? lanzamos una Exception? Mostramos un mensaje? Lo haremos configurable.

private static void CheckPropertyInfo(string propertyName, PropertyInfo propertyInfo, bool throwExceptions)
{
    if (propertyInfo == null)
    {
        if (throwExceptions)
        {
            throw new Exception(String.Format("Argumento {0} no reconocido", propertyName));
        }
        else
        {
            Console.WriteLine("Argumento {0} no reconocido", propertyName);
        }
    }
}

También, para el caso de parámetros que deban admitir un valor, necesitaremos obtener, por un lado nombre, y por otro el valor de la propiedad.

private static string[] SplitArgument(string argument)
{
    string[] argumentParts = new string[] { argument, argument };

    if (argument.Contains("="))
    {
        argumentParts = argument.Split('=');
    }

    return argumentParts;
}

Este método, devolverá un string con 2 posiciones en la que la primera corresponderá al nombre del argumento, y la segunda al valor. El separador nombre/valor es el signo igual. Si no se especifica este nombre=valor, devolveremos el nombre en las dos posiciones.

Queda convertir una string al tipo de la propiedad.

private static object GetValue(PropertyInfo propertyInfo, string value)
{
    // Instanciamos el valor de retorno
    Object returnValue = null;
    if (propertyInfo.PropertyType.IsEnum)
    {
        // Si el tipo de la propiedad es un enum, lo parseamos, ignorando el casing 
        returnValue = Enum.Parse(propertyInfo.PropertyType, value, true);
    }
    else if (propertyInfo.PropertyType == typeof(bool))
    {
        // Si el tipo de la propiedad es un bool, será true siempre.
        // Este es el caso de los modificadores
        // Si el usuario lo ha mencionado en la línea de comandos es porque quiere el modificador
        returnValue = true;
    }
    else if (propertyInfo.PropertyType == typeof(DateTime?))
    {
        // Si es de tipo fecha, lo parseamos
        returnValue = (object)DateTime.Parse(value);
    }
    else
    {
        // Si no es ninguno de esos tipos, intentamos una conversión directa
        returnValue = value;
    }
    // Devolvemos.
    // Si hubieran habido problemas de formato del valor, se habría disparado 
    // una excepción en la conversión
    return returnValue;
}

Asignamos el valor convertido a la propiedad

private static void SetPropertyValue(object objectInstance, PropertyInfo propertyInfo, string value)
{
    Object castedValue = GetValue(propertyInfo, value);
    propertyInfo.SetValue(objectInstance, castedValue, null);
}

Y finalmente, lo montamos todo.

Un requerimiento de última hora (nunca faltan). Si mi aplicación es de las de “una aplicación varios comandos” no vamos a escribir MiAplicacion.exe command=Get
El método debería ser lo bastante listo para saber que el primer parámetro corresponde al comando que queremos ejecutar y debe ser asignado a la propiedad Command.

// Instanciamos el valor de retorno
T retVal = new T();
// Obtenemos el tipo de retorno
Type argumentsEntityType = typeof(T);
// Iteramos sobre los elementos de args
for (int i = 0; i < args.Length; i++)
{
    // Separamos el nombre/valor
    string[] argumentParts = SplitArgument(args[i]);
    if (i == 0 && firstArgumentMustBeCommand)
    {
        // Si hemos indicado que el primer parámetro debe ser el comando, 
        // diremos que su nombre es Command
        argumentParts[0] = "Command";
    }
    // Obtenemos la PropertyInfo correspondiente
    PropertyInfo propInfo = GetPropertyInfo(argumentParts[0], argumentsEntityType);
    // Mostramos mensaje o lanzamos excepción si no la hemos podido obtener
    CheckPropertyInfo(argumentParts[0], propInfo, throwExceptions);
    // Si hemos podido obtenerla
    if (propInfo != null)
    {
        // Le establecemos el valor
        SetPropertyValue(retVal, propInfo, argumentParts[1]);
    }
}
return retVal;

 

Y voilá. Ya lo tenemos. ¿Cómo se usa?

class Program
{
    static void Main(string[] args)
    {
        MyArguments myArgs = ArgumentsHandler.Get<MyArguments>(args);
        Console.WriteLine(Environment.CommandLine);
        Console.WriteLine("Command: {0}", myArgs.Command.ToString());
        Console.WriteLine("UserName: {0}", myArgs.UserName);
        Console.WriteLine("Password: {0}", myArgs.Password);
        Console.WriteLine("FileName: {0}", myArgs.FileName);
        Console.WriteLine("Format: {0}", myArgs.Format.ToString());
        Console.WriteLine("StartDate: {0}", myArgs.StartDate.ToString());

        Console.WriteLine("ShowProgress: {0}", myArgs.ShowProgress.ToString());
        Console.WriteLine("Overwrite: {0}", myArgs.Overwrite.ToString());
    }
}

 

Para una línea de comandos del tipo
Set UserName=crisfervil qwerty PASSWORD=pepe SHOWPROGRESS FileName=”c:\Program Files\Test.txt” Format=doc StartDate=31/03/2007 asdf

La salida será

image

Tengo previsto añadirle mejoras, como la posibilidad de definir atributos a las propiedades para identificar sinónimos. Por ejemplo, poder escribir -p en lugar de showprogress. Pero eso, para la v 2.0

Crossposted from crisfervil.com

Scaffolding

Archivado en: General — crisfervil @ 12:04 pm

Aprovecho un rato libre para un post fugaz.

Mientras leo en el blog de mi amigo Scott Guthrie (más quisiera ;p) las novedades que introduce el SP1 para Visual Studio 2008 y el .NET Framework 3.5, me encuentro con un termino extraño y nuevo. Scaffolding. Y qué narices es eso?

Pues parece ser que se trata de un término que cuya traducción literal es Andamio, pero que hace referencia a la utilidad que ofrecen algunos IDEs para construir – de una forma relativamente rápida y sencilla – aplicaciones que tiran contra bases de datos.

La idea del Scaffolding es permitir al programador especificar mediante algún DSL la estructura de la base de datos, y a partir de ahí, generar automáticamente la lógica y la presentación. La tarea del programador por lo tanto consistirá en “personalizar” lo generado, añadiendo la lógica específica de la aplicación.

Los IDEs precursores del Scaffolding han sido – entre otros – Ruby on Rails , CakePHP y Symphony. Ahora además lo tenemos disponible en VS 2008 para ASP.net.

 

image

Con .NEt 3.5 SP1, VS 2008 soporta ahora la creación de aplicaciones ASP.net sobre el “data scaffolding framework” que permite levantar rápidamente aplicaciones web de acceso a datos. Con la característica ASP.NET Dynamic Data, se podrá construir automáticamente la UI, con soporte total para CRUD (Create, Read, Update y Delete), además de una variedad de modelos de objetos, incluyendo LINQ to SQL, LINQ to Entities, Servicios REST, y cualquier otro ORM que soporte el modelo Dynamic Data Provider.

image

EL SP1 agrega esta nueva funcionalidad a los controles GridView, ListView, DetailsView y FormView existentes y permite agregar validaciones y especificar templates. Además se permite la creación de controles de filtrado, soporte para la creación de relaciones clave-primaria/clave-foránea, etc, etc ,etc. con el consecuente ahorro de código, y de tiempo.

image

Aquí, hay un vídeo de Scott Hanselman en el que construye una aplicación de ejemplo usando la funcionalidad de Scaffolding.

image

image

Nunca te acostarás sin saber dos o tres cosas más.

Crossposted from crisfervil.com

09/05/08

Text Entity Serializer

Archivado en: General — crisfervil @ 8:22 pm

Serializador de Entidades en formato texto.

Dejo este snippet por si a alguno le puede ser de utilidad.

Resuelve el problema de guardar una lista de entidades (resultados de una búsqueda, una consulta, etc.) en un archivo de texto, con un delimitador.

Muy a pesar de muchos, aun siguen habiendo proyectos en los que es necesario trabajar con este formato en lugar de usar xml.

La idea es usar la reflexión para serializar los textos que se usarán para las cabeceras, y a partir de ahí, los valores de los campos.

Es una clase genérica, expone entre otras cosas un método

public string Serialize(List<T> items)

Lo primero que hacemos en este método es obtener el tipo de T.

Type objectType = typeof(T);

Es bien sabido que para trabajar con cadenas, es más óptimo usar la clase StringBuilder

StringBuilder outPut = new StringBuilder();

Para crear los encabezados,  recorremos las propiedades públicas del tipo, y escribimos su nombre

// Escribir Encabezados
/* GetProperties() devuelve las propiedades públicas de la clase */
foreach (PropertyInfo item in objectType.GetProperties())
{
    outPut.Append(item.Name);
    outPut.Append(_fieldSeparator);
}
outPut.Append(_rowSeparator);

el siguiente paso, será escribir los valores de las propiedades de cada uno de los items recibidos en la llamada al método:

// Escribir Valores
foreach (T item in items)
{
    foreach (PropertyInfo propertyItem in objectType.GetProperties())
    {
        // Obtenemos el valor del campo
        object value = propertyItem.GetValue(item, null);
        if(value!=null)
        {
            // Escribir valor del campo
            outPut.Append(value.ToString());
        }else{
            // Escribir cadena que representa valor nulo
            outPut.Append(_nullString);
        }
        // Escribir separador de campos
        outPut.Append(_fieldSeparator);
    }
    // Escribir separador de registros
    outPut.Append(_rowSeparator);
}

Y.. finalmente, devolver la cadena generada, que podremos escribir en un fichero

// Valor de retorno
return outPut.ToString();

Por supuesto, creamos una sobrecarga para escribir lo generado en un archivo:

public string Serialize(List<T> items, string fileName)

Y… lo escribimos con un StreamWriter

// Creamos instancia del Writer
// El using permitirá que se liberen los recursos del sistema
// en caso de error, a la vez que se propaga la excepción
using (StreamWriter sw = new StreamWriter(fileName))
{
    // Escribimos
    sw.Write(textToWrite);
    // Cerramos Fichero
    sw.Close();
}

Y voilá. Ya tenemos todo lo necesario.

Cómo usar la clase?

// Buscamos clientes de Madrid
List<Cliente> resultados = BuscarClientes("Madrid");
// Instanciamos el serializador
TextSerializer<Cliente> clientesSerializer = new TextSerializer<Cliente>();
// Guardamos el archivo. Lo creamos con la extensión xls para poder
// verlo con el Excel, que es más cómodo
clientesSerializer.Serialize(resultados, "Clientes_Madrid.xls");

image

Y ya que estamos: Dejo este otro snippet para serializar la misma lista de entidades, pero en formato xml.

// Serializar los resultados a xml
using (FileStream fs = new FileStream("Clientes_Madrid.xml", FileMode.Create))
{
    System.Xml.Serialization.XmlSerializer xs = new XmlSerializer(typeof(List<Cliente>));
    xs.Serialize(fs, resultados);
    fs.Close();
}

image 

Crossposted from crisfervil.com

Blog de WordPress.com.