Categoría: cosas técnicas

Posts relacionados con la programación o manejo o configuración de los oredenadores (computadores)

  • Compilar y ejecutar (utilidad para .NET)

    Pues eso… esta utilidad la publiqué el 5 de enero de 2019, pero solo en elguille.info (Utilidades para .NET: Compilar y ejecutar) y aparte del código fuente puse la opción de instalarla usando ClickOnce.

    En esa ocasión utilizaba código de Roslyn 2.0.1 (Microsoft.CodeDom.Providers.DotNetCompilerPlatform) para compilar el código desde la aplicación: se tomaba el código (un texto) de Visual Basic o C#, se compilaba y se mostraba el resultado por la consola virtual usada en la aplicación, de modo que pudieras ver el resultado de la salida.

    Algo como lo mostrado en la siguiente captura, donde el panel superior es el código y el inferior es la salida al compilar y ejecutar dicho código.

     

    El código de esa utilidad lo he cambiado con fecha del 30 y 31 de agosto de 2020, entre otras cosas para usar Roslyn 3.6.0, que actualmente es la versión más reciente.

    Y el escribir esto aquí, en el blog, es para comentarte que al usar esa nueva versión del paquete de NuGet daba error al ejecutar el código (y pulsar en el botón de compilar).

    El error era que no encontraba el compilador de Visual Basic (vbc.exe) o C# (csc.exe) y el path que daba era el path del ejecutable seguido de bin\roslyn, por ejemplo: «<resto del path>\bin\roslyn\vbc.exe»

    Yo ya estaba por desistir y dejar la versión 2.0.1 de Roslyn ya que al fin y al cabo me permitía usar la versión más reciente de los compiladores de VB y C#, pero buscando en el NuGet del CodeDom.Providers.DotNetCompilerPlatform de Roslyn 3.6.0 y concretamente al mirar en el enlace que hay debajo de «This package was built from the source at» me llevó al GitHub de aspnet / RoslynCodeDomProvider. Y mirando en las Issues (había 3) me topé con la de WolfgangHG con el título: [3.6.0] Missing entry «aspnet:RoslynCompilerLocation» in app.config causes compile to fail, y eso era todo lo que hacía falta… añadir un trozo de código que en teoría faltaba para que funcionara a la perfección (ese código si se incluye en roslyn 2.0.1) y es este:

      <appSettings>
        <add key="aspnet:RoslynCompilerLocation" value="roslyn"/>
      </appSettings>
    

    Y ya si quieres, cambia la asignación de compilerOptions de C# y VB (en la sección system.codedom / compilers) para que la versión del compilador sea la predeterminada: /langversion:default. Ya que en mi caso, la versión de C# estaba en la 7.3 y se puede usar la 8.0. Con Visual Basic, la «default» es la versión 16 (la última hasta la fecha de hoy).

    En la siguiente captura puedes ver las versiones que aceptan los compiladores vbc.exe y csc.exe en el Roslyn 3.6.0:

    Versiones de los lenguajes de VB y C# soportadas por los compiladores incluidos en Roslyn 3.6.0

    Como ves, la versión predeterminada (y la mayor) de vbc.exe en la 16, mientras que la del compilador de C# (csc.exe) es la 8.0.

    NOTA:
    En la preview de Visual Studio 2019 la versión más alta de C# es la 9.0, la de VB sigue siendo la 16.

    Nota:
    Desde la página de la utilidad en elguille.info puedes instalarla con ClickOnce y tienes el código fuente de la utilidad (en Visual Basic) y algunos ejemplos tanto en VB como en C#.

    Nos vemos.
    Guillermo

  • Cálculos aritméticos en tu código con EvaluarExpresiones

    Pues eso… ya he corregido y actualizado el código de evaluar expresiones aritméticas que publiqué inicialmente en octubre de 2007. Además he ampliado la funcionalidad que tenía usando algunas cosas que ya hacía en la versión que creé en su día con Visual Basic 6 (cFormulas – Una clase para analizar expresiones numéricas).

    Como por ejemplo poder definir variables y funciones propias, además de poder usar contenido entre comillas dobles (solo para mostrar, no es que utilice variables alfanuméricas).

    Para usar el «evaluador de expresiones» necesitas tener una referencia a la DLL (elGuille.EvaluarExpresiones.dll) en tu proyecto de .NET (al menos funciona con Visual Basic y C#) y tener instalado al menos el .NET 4.7.

    Crear una variable a la que asignes una nueva instancia de elGuille.Developer.EvaluarFunciones.
    Dim ev As New elGuille.Developer.EvaluarFunciones.

    Si quieres añadir variables antes de empezar a usar el método Evalua, lo puedes hacer con ev.NewVariable(«A», «123+5+2″) y si quieres crear una función, hazlo con ev.NewFunction(«Doble», «N», «N*2»). Si quieres hacer varias asignaciones de un golpe, puedes usar ev.AsignarVariables(«C=A+B: D=12345: F=A*D»).

    Y para evaluar las diferentes expresiones usa el método Evalua al que le pasarás como argumento una cadena con el «texto» a evaluar, por ejemplo:
    resultado = ev.Evalua(«X=10:A=5*3: P=3.14: X + A + P»)

    Descargar el código fuente y la DLL

    El código completo de la DLL está en EvaluarExpresiones_src.zip que tiene un tamaño de 191 KB (195.897 bytes) y que puedes descargar pulsando directamente en el enlace anterior (está en el sitio downloads.elguille.info).
    Revisión v.58 del 29/Ago/2020

    Ese código es un proyecto de Visual Basic .NET.

    En otra ocasión actualizaré este artículo para poner algunos ejemplos de uso. Aunque los publicados en los dos enlaces que te puse al principio te pueden servir.

    Espero que te sea de utilidad… ya sabes… de eso es de lo que se trata 😉

    Nos vemos.
    Guillermo

  • Métodos de extensión (ejemplos para Visual Basic y C#)

    Pues eso… y por si no lo sabes, esto de los métodos de extensión (Extension Methods en inglés) sirve para ampliar la funcionalidad de clases existentes, ya sean definidas en el propio .NET (String, Integer, TextBox, etc.) como en otras librerías (bibliotecas) que tengamos referenciadas en nuestro proyecto.

    NOTA:
    Aquí no te voy a explicar en detalle de qué va esto de los métodos de extensión, solo decirte cómo crear los tuyos propios, con código de Visual Basic y de C#, para ello te pondré unos ejemplos.

    NOTA2:
    ¡Vaya despiste!
    Pues eso… que se ve que en septiembre del año pasado (5-sep-2019) ya publiqué algo sobre los métodos de extensión… y es que lo tenía apuntado (en mi cabeza) y se ve que después de publicarlo no lo borré… jajaja… en fin… Más vale 2 que nada… 😉

    En este artículo voy a ponerte un par de ejemplos para añadir una nueva función a la clase String y algunos métodos de conversión a la clase TextBox, de forma que puedas usarlos para convertir el contenido de la propiedad Text en un valor entero, un valor decimal, etc.

    Crear métodos de extensión en Visual Basic

    En Visual Basic necesitamos una importación a System.Runtime.CompilerServices y crear los métodos en un módulo (no se pueden crear en clases).
    La definición del método empezará con el atributo <Extension> y después seguirá la definición de la función ( o método), pero en el primer parámetro indicaremos la clase que queremos ampliar (o extender) y después, opcionalmente, podemos usar más parámetros.

    Crear método de extensión en C#

    Para crear métodos de extensión en C# necesitamos una clase definida como static y definir los métodos de extensión también como compartidos (static), pero no es necesario usar la importación de CompilerServices ni añadir el atributo Extension, ya que el compilador sabe que es un método de extensión si el primer argumento de la función (o método) empieza con this y el tipo que queremos extender.

    Un par de ejemplos de métodos de extensión

    En el siguiente código tenemos un par de ejemplos de métodos de extensión de la clase String, el primero como función y el segundo como un método que no devuelve nada.
    Primero el código de Visual Basic y después el de C#.

    Imports System.Runtime.CompilerServices
    
    Module Extensiones
        <Extension>
        Public Function Prueba(str As String) As String
            Return "PRUEBA " & str
        End Function
    
        <Extension>
        Public Sub Imprimir(str As String)
            Console.WriteLine(str)
        End Sub
    End Module
    
    static class Extensiones
    {
        //[Extension]
        public static string Prueba(this string str)
        {
            return "PRUEBA " + str;
        }
    
        public static void Imprimir(this string str)
        {
            Console.WriteLine(str);
        }
    

    Algunos métodos prácticos para extender String y TextBox

    Aquí te dejo el código para extender la clase String con un método que quita las tildes (acentos) a las vocales, con idea de que podamos hacer comparaciones sin que se tenga en cuenta si la vocal está o no acentuada (con la tilde).

    En el caso del control TextBox te dejo los métodos de extensión para convertir el contenido en un valor de tipo Integer, Double, Decimal, Date y TimeSpan.
    Esto lo empecé a usar en el último programa que he hecho, hasta ahora, cuando quería convertir el contenido de una cadena en un valor numérico, etc., lo que hacía era usar funciones para esas conversiones.
    Esas conversiones podría haberlas puesto en la clase String, pero al hacerla en el TextBox me ahorraba tener que indicar la propiedad Text cada vez que quería hacer la conversión 😉
    En el código de ejemplo te pongo también la función que convierte en número entero para la clase String, así lo tendrás fácil si quieres extender dicha clase en lugar del TextBox.

    El código para Visual Basic

    Primero los métodos de extensión y después cómo usarlos.

    Imports System
    
    Imports System.Runtime.CompilerServices
    Imports System.Windows.Forms
    
    Module Extensiones
    
        ''' <summary>
        ''' Devuelve un valor Integer de la propiedad Text del TextBox indicado.
        ''' </summary>
        ''' <param name="txt">El TextBox a extender</param>
        <Extension>
        Public Function AsInteger(txt As TextBox) As Integer
            Dim i As Integer = 0
    
            Integer.TryParse(txt.Text, i)
    
            Return i
        End Function
    
        ''' <summary>
        ''' Devuelve un valor Double de la propiedad Text del TextBox indicado.
        ''' </summary>
        <Extension>
        Public Function AsDouble(txt As TextBox) As Double
            Dim d As Double = 0
    
            Double.TryParse(txt.Text, d)
    
            Return d
        End Function
    
        ''' <summary>
        ''' Devuelve un valor Decimal de la propiedad Text del TextBox indicado.
        ''' </summary>
        <Extension>
        Public Function AsDecimal(txt As TextBox) As Decimal
            Dim d As Decimal = 0
    
            Decimal.TryParse(txt.Text, d)
    
            Return d
        End Function
    
        ''' <summary>
        ''' Devuelve un valor TimeSpan de la propiedad Text del TextBox indicado.
        ''' </summary>
        <Extension>
        Public Function AsTimeSpan(txt As TextBox) As TimeSpan
            Dim c As New TimeSpan(0, 0, 0)
    
            TimeSpan.TryParse(txt.Text, c)
    
            Return c
        End Function
    
        ''' <summary>
        ''' Devuelve un valor Date de la propiedad Text del TextBox indicado.
        ''' Si es un valor nulo o vacío, devuelve el 1 de enero de 1900.
        ''' </summary>
        <Extension>
        Public Function AsDate(txt As TextBox) As Date
            Dim d As DateTime = New DateTime(1900, 1, 1)
    
            If Not (String.IsNullOrWhiteSpace(txt.Text) OrElse txt.Text.Equals(DBNull.Value)) Then
                DateTime.TryParse(txt.Text, d)
                If d.Year < 1900 Then
                    d = New DateTime(1900, 1, 1, 0, 0, 0)
                End If
            Else
                ' asignar el 01/01/1900 si es un valor en blanco
                d = New DateTime(1900, 1, 1, 0, 0, 0)
            End If
    
            Return d.Date
        End Function
    
    
        ''' <summary>
        ''' Quitar las tildes de una cadena.
        ''' </summary>
        ''' <param name="str">La cadena a extender</param>
        <Extension>
        Public Function QuitarTildes(ByVal str As String) As String
            Dim tildes1 = "ÁÉÍÓÚáéíóú"
            Dim tildes0 = "AEIOUaeiou"
            Dim res As New System.Text.StringBuilder
    
            For i = 0 To str.Length - 1
                Dim j = tildes1.IndexOf(str(i))
                If j > -1 Then
                    res.Append(tildes0.Substring(j, 1))
                Else
                    res.Append(str(i))
                End If
            Next
            Return res.ToString
        End Function
    
        ''' <summary>
        ''' Devuelve un valor Integer de la cadena a la que se aplica este método.
        ''' </summary>
        <Extension>
        Public Function AsInteger(str As String) As Integer
            Dim i As Integer = 0
    
            Integer.TryParse(str, i)
    
            Return i
        End Function
    
    
    
        <Extension>
        Public Function Prueba(str As String) As String
            Return "PRUEBA " & str
        End Function
    
        <Extension>
        Public Sub Imprimir(str As String)
            Console.WriteLine(str)
        End Sub
    End Module
    
    Imports System
    
    Imports System.Windows.Forms
    
    Module Module1
    
        Sub Main()
            Dim s = "Hola"
            Console.WriteLine(s.Prueba)
    
            s.Imprimir()
    
            s = "Código de ejemplos prácticos"
            Console.WriteLine(s.QuitarTildes())
    
            Dim txt As New TextBox
    
            txt.Text = "125"
            Console.WriteLine("txt.Text : {0}", txt.Text)
            Console.WriteLine("txt.Text.AsInteger+10 : {0}", txt.Text.AsInteger + 10)
            Console.WriteLine("txt.AsInteger+10 : {0}", txt.AsInteger + 10)
    
            txt.Text = "125,38"
            Console.WriteLine("txt.Text : {0}", txt.Text)
            Console.WriteLine("txt.AsDecimal*2 : {0}", txt.AsDecimal * 2)
            Console.WriteLine("txt.AsDouble*2 : {0}", txt.AsDouble * 2)
    
            txt.Text = "10:30"
            Console.WriteLine("txt.Text : {0}", txt.Text)
            Console.WriteLine("txt.AsTimeSpan : {0}", txt.AsTimeSpan)
    
            txt.Text = "24/08/2020"
            Console.WriteLine("txt.Text : {0}", txt.Text)
            Console.WriteLine("txt.AsDate : {0}", txt.AsDate)
            Console.WriteLine("txt.AsDate.AddDays(2) : {0}", txt.AsDate.AddDays(2))
    
    
            Console.ReadKey()
        End Sub
    
    End Module
    

    El código para C#

    Primero los métodos de extensión y después cómo usarlos.

    using System;
    using System.Windows.Forms;
    
    static class Extensiones
    {
        //[Extension]
        public static string Prueba(this string str)
        {
            return "PRUEBA " + str;
        }
    
        public static void Imprimir(this string str)
        {
            Console.WriteLine(str);
        }
    
        /// <summary>
        /// Devuelve un valor Integer de la propiedad Text del TextBox indicado.
        /// </summary>
        /// <param name="txt">El TextBox a extender</param>
        public static int AsInteger(this TextBox txt)
        {
            int i = 0;
    
            int.TryParse(txt.Text, out i);
    
            return i;
        }
    
        /// <summary>
        /// Devuelve un valor Double de la propiedad Text del TextBox indicado.
        /// </summary>
        public static double AsDouble(this TextBox txt)
        {
            double d = 0;
    
            double.TryParse(txt.Text, out d);
    
            return d;
        }
    
        /// <summary>
        /// Devuelve un valor Decimal de la propiedad Text del TextBox indicado.
        /// </summary>
        public static decimal AsDecimal(this TextBox txt)
        {
            decimal d = 0;
    
            decimal.TryParse(txt.Text, out d);
    
            return d;
        }
    
        /// <summary>
        /// Devuelve un valor TimeSpan de la propiedad Text del TextBox indicado.
        /// </summary>
        public static TimeSpan AsTimeSpan(this TextBox txt)
        {
            TimeSpan c = new TimeSpan(0, 0, 0);
    
            TimeSpan.TryParse(txt.Text, out c);
    
            return c;
        }
    
        /// <summary>
        /// Devuelve un valor Date de la propiedad Text del TextBox indicado.
        /// Si es un valor nulo o vacío, devuelve el 1 de enero de 1900.
        /// </summary>
        public static DateTime AsDate(this TextBox txt)
        {
            DateTime d = new DateTime(1900, 1, 1);
    
            if (!(string.IsNullOrWhiteSpace(txt.Text) || txt.Text.Equals(DBNull.Value)))
            {
                DateTime.TryParse(txt.Text, out d);
                if (d.Year < 1900)
                    d = new DateTime(1900, 1, 1, 0, 0, 0);
            }
            else
                // asignar el 01/01/1900 si es un valor en blanco
                d = new DateTime(1900, 1, 1, 0, 0, 0);
    
            return d.Date;
        }
    
    
        /// <summary>
        /// Quitar las tildes de una cadena.
        /// </summary>
        /// <param name="str">La cadena a extender</param>
        public static string QuitarTildes(this string str)
        {
            var tildes1 = "ÁÉÍÓÚáéíóú";
            var tildes0 = "AEIOUaeiou";
            System.Text.StringBuilder res = new System.Text.StringBuilder();
    
            for (var i = 0; i <= str.Length - 1; i++)
            {
                var j = tildes1.IndexOf(str[i]);
                if (j > -1)
                    res.Append(tildes0.Substring(j, 1));
                else
                    res.Append(str[i]);
            }
            return res.ToString();
        }
    
        /// <summary>
        /// Devuelve un valor Integer de la cadena a la que se aplica este método.
        /// </summary>
        public static int AsInteger(this string str)
        {
            int i = 0;
    
            int.TryParse(str, out i);
    
            return i;
        }
    }
    
    using System;
    
    using System.Windows.Forms;
    
    class Program
    {
        static void Main(string[] args)
        {
            var s = "Hola";
            Console.WriteLine(s.Prueba());
            //Console.WriteLine(s.Prueba2());
    
            s.Imprimir();
    
            s = "Código de ejemplos prácticos";
            Console.WriteLine(s.QuitarTildes());
    
    
            TextBox txt = new TextBox();
    
            txt.Text = "125";
            Console.WriteLine("txt.Text : {0}", txt.Text);
            Console.WriteLine("txt.Text.AsInteger+10 : {0}", txt.Text.AsInteger() + 10);
            Console.WriteLine("txt.AsInteger+10 : {0}", txt.AsInteger() + 10);
    
            txt.Text = "125,38";
            Console.WriteLine("txt.Text : {0}", txt.Text);
            Console.WriteLine("txt.AsDecimal*2 : {0}", txt.AsDecimal() * 2);
            Console.WriteLine("txt.AsDouble*2 : {0}", txt.AsDouble() * 2);
    
            txt.Text = "10:30";
            Console.WriteLine("txt.Text : {0}", txt.Text);
            Console.WriteLine("txt.AsTimeSpan : {0}", txt.AsTimeSpan());
    
            txt.Text = "24/08/2020";
            Console.WriteLine("txt.Text : {0}", txt.Text);
            Console.WriteLine("txt.AsDate : {0}", txt.AsDate());
            Console.WriteLine("txt.AsDate.AddDays(2) : {0}", txt.AsDate().AddDays(2));
    
    
            Console.ReadKey();
        }
    
        //Error CS1106: Un método de extensión debe definirse en una clase estática no genérica
    
        //public static string Prueba2(this string str)
        //{
        //    return "PRUEBA2 " + str;
        //}
    
    }
    

    Y esto es todo… espero que te haya sido de utilidad… ya sabes que esa es la idea 😉

    Nos vemos.
    Guillermo