Archivo por días: 5 enero, 2013

Mis primeras fotos del 2013

 

Pues eso… que esta mañana he estado dando un paseillo por el Pinarillo (y alrededores) con mi amiga Ana… aquí te dejo algunas fotos (las que he publicado en Facebook), algunas están con "efectos"… jugueteando con el móvil, jeje…

Si quieres ver el álbum en mi perfil de Facebook:
Por el Pinarillo, sábado 5 de enero de 2013

 


El dragón

 


¡Que no llego! Aprendiendo a escalar… aunque no como mi colega Luis (Vesperino Vespa)

 


agarrando las ramas pa que no me salten un ojo…


Yo veo tres caras… ¿cuántas ves tú?

 


de arriba a abajo… por aquí…

 


de arriba a abajo… por allá…

 


¡por ahí no! (que el suelo está mu duro)

 


otro punto de vista del columpio…

 


¡vamos a echar una carrera comlumpianista!

 

 


Simplemente me gusta…

 


llamaradas en el Pinarillo? (no, jugueteando con el móvil)

 


el Pinarillo al estilo Polaroid

 

Y ya está… hay más fotos,. pero tampoco es plan de ponerlas todas… cuando publique el álbum en Picasa web ya avisaré…

 

Nos vemos.
Guillermo

[FB] 05 Ene, 05:52 – que zuhto!!!

Publicado en Facebook el January 05, 2013 at 05:52AM:

que zu’to! cuando he vaciao la papelera de reciclaje (del Windows) y he visto que había más de 4000 ficheros (cuatro mil seiscientos y pico)… después de darle a vaciar y mientras pensaba qué podía haber hecho para tener tanta «basura», pues que no me ha dado tiempo a cancelar… como para que hubieran sido ficheros válidos…
Pero después me he he acordado de que ayer borré una carpeta que tenía sincronizada con SkyDrive (tenía acento/tilde y creé una nueva) y… sí, tiene algo más de cuatro mil ficheros, pero no llega a los 4500, así que… el resto será de las miles de pruebas que he estado haciendo estos días… ¡espero!

Por cierto, quiero pedirle a los Reyes Magos un ecl o nue o que ste y me f^ll@… 😉
 
Nos vemos.
Guillermo

#delfeis #ifttt #elguilleinfo

Crear un objeto a partir de una cadena con Activator.CreateInstance

 

Pues eso… como el título indica, te voy a explicar cómo crear (instanciar sería más correcto) un objeto a partir del "nombre" de una clase, pero estando ese nombre dentro de una cadena. Y como de costumbre, con el código de ejemplo tanto para (mi querido) Visual Basic como para (mi obligado) C# 😉

Lo de "obligado" también lo puedes tomar por "obrigado" que en portugués significa "gracias", de agradecimiento, no te vayas a pensar que el C# me hace gracia… bueno, algunas veces me hago a la idea que me está guiñando… (por lo del punto y coma) 😉

 

Vamos al tema.

Si tienes una cadena con el nombre de una clase, puedes crear una nueva instancia de esa clase utilizando la clase Activator, más concretamente el método compartido CreateInstance.

Para que funcione la conversión de cadena a objeto del tipo correcto debes tener en cuenta que:

  1. Indiques el espacio de nombres del tipo en la cadena
  2. La clase puede ser una clase derivada (o implementada)
  3. El tipo tenga un constructor público y sin parámetros
  4. Las clases abstractas (abstract / MustInherit) no sirven ya que no se pueden instanciar
  5. Que la clase a crear esté accesible, vamos que si tú no puedes crear el objeto ni indicando el tipo de forma explícita el Activator no creo que haga milagros…

 

Una vez que sabemos las condiciones que debemos seguir para instanciar clases a partir del contenido de un string vamos a ponerlo a prueba con unos ejemplos en los que comprobaremos lo dicho en la lista anterior y algo más.

El código para hacer la conversión lo podemos simplificar al máximo, pero en ese caso sólo deberíamos usarlo para crear clases que cumplan las 2 primeras condiciones indicadas en la lista anterior.
Para casos indicados en los puntos 3 y 4 habría que usar un bloque try/catch para detectar la excepción que ocurrirá, ya que el tipo es correcto pero no se puede instanciar.
Para los casos que cumplan la última condición (el tipo no existe o no está accesible) podemos usar una comprobación que en realidad es para saber si el tipo es del mismo tipo a convertir o se deriva de él, esa comprobación la haremos por medio del método IsAssignableFrom (definido en la clase Type).

Veamos primero el código que hace la conversión sin más comprobaciones 
(el código completo lo he puesto en un método para que sea más fácil hacer varias de las pruebas).

VB:

Dim laClase = "ActivatorVB.Colega"

Dim elTipo As Type = Type.GetType(laClase)

Dim obj As Colega = TryCast(Activator.CreateInstance(elTipo), Colega)

If obj IsNot Nothing Then
    obj.Nombre = "Pepe"
    obj.Email = "pepe@outlook.com"
End If

 

C#:

var laClase = "ActivatorCS.Colega";

Type elTipo = Type.GetType(laClase);

Colega obj = Activator.CreateInstance(elTipo) as Colega;

if (obj != null)
{
    obj.Nombre = "Pepe";
    obj.Email = "pepe@outlook.com";
}

 

Un par de aclaraciones (tanto para VB como para C#, las aclaraciones) sobre este código:

En VB utilizo TryCast y en C# utilizo as para hacer la conversión ya que de esa forma, si el objeto no se puede crear se devuelve un valor nulo.

Si en VB utilizara CType o DirectCast o en C# hiciera la conversión con (Colega) y la conversión falla, produciría un error.

Aunque en realidad esto sólo nos salvará de los casos indicados en el punto 5 de las "condiciones" para realizar la instanciación de la clase a partir de una cadena. Pero bueno, ya sabes que hay varias formas de hacer conversiones entre tipos 😉

 

Para hacer la comprobación de si el tipo es adecuado por medio del método IsAssignableFrom lo haríamos de la siguiente forma:

 

'  VB
' Esto controlará las clases que no se basan en Colega
If Not GetType(Colega).IsAssignableFrom(elTipo) Then Console.WriteLine("El tipo: {0} no es del tipo adecuado." & vbLf & "", laClase) Return End If // C# // Esto controlará las clases que no se basan en Colega if (!typeof(Colega).IsAssignableFrom(elTipo)) { Console.WriteLine("El tipo: {0} no es del tipo adecuado.\n", laClase); return; }

 

Ya solo me queda ponerte todo el código de prueba en el que he hecho las pruebas esas que conforman la lista para estar seguro de que es así…

Te recomiendo que hagas tú las tuyas propias, incluso usando las partes comentadas en dicho código.

En el método Main2 de dicho código he puesto un ejemplo de una clase que implementa una interfaz.

 

Nota:

El código completo lo pongo aparte para que no llene tanto esto.

Además te pongo separado el de Visual Basic de el de C# y tu eliges el que quieras.

También está publicado en Pastebin.

 

Espero que te sea de utilidad.

Nos vemos.

Guillermo

P.S.

Los enlaces:

El de VB en Pastebin

El de C# en Pastebin

El de VB en mi blog

El de C# en mi blog

elGuille_luna300x200

Código de cómo instanciar una clase a partir del contenido de una cadena (C#)

 

Lo dicho el código completo para Visual Basic del ejemplo comentado en:

Crear un objeto a partir de una cadena con Activator.CreateInstance

(el enlace al de Visual Basic está en ese mismo artículo)

 

//-----------------------------------------------------------------------------
// Crear un objeto a partir de una cadena con Activator             (05/Ene/13)
//
//
// ©Guillermo 'guille' Som, 2013
//-----------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace ActivatorCS
{
    public sealed class CrearClase
    {

        public static void Main()
        {
            // La clase a crear
            var elNombre = "ActivatorCS.Colega";

            crearColega(elNombre);


            // Esta clase se llama igual,
            // pero no es del mismo tipo
            // y no pasaría la prueba de IsAssignableFrom,
            // aunque no daría error al hacer la conversión
            // pero no crearía una instancia,
            // por tanto Activator devolvería nulo,
            // en realidad el valor nulo lo devuelve
            // la operación de conversión de tipos
            // por eso en C# utilizo "as Colega" en lugar de "(Colega)"
            // para hacer la conversión
            elNombre = "OtroEspacio.Colega";
            crearColega(elNombre);

            // esta clase se basa en la que queremos crear
            // aunque esté en otro espacio de nombres
            elNombre = "OtroEspacio.Coleguilla";
            crearColega(elNombre);

            // este tipo no existe,
            // pero debemos usar IsAssignableFrom
            // para no provocar una excepción
            elNombre = "Activator.Colega";
            crearColega(elNombre);

            // esta se basa en la nuestra
            // pero es abstracta (no tiene constructor)
            // ya dará un error al crearla
            // aunque pasaría la prueba de IsAssignableFrom
            try
            {
                elNombre = "ActivatorCS.ColegaAbstracto";
                crearColega(elNombre);

            }
            catch (Exception ex)
            {
                Console.WriteLine("Mrw! (o Ups!) esta clase {0} da error: {1}",
                                  elNombre, ex.Message);

            }

            Console.ReadKey();

        }

        private static void crearColega(string laClase)
        {
            Type elTipo = Type.GetType(laClase);

            // el equivalente en c# de TryCast es hacer el cast con "as tipo"
            // aunque también se puede comprobar si se puede crear el objeto

            // Esto contralará las clases que no se basan en Colega
            if (!typeof(Colega).IsAssignableFrom(elTipo))
            {
                Console.WriteLine("El tipo: {0} no es del tipo adecuado.\n", 
                                  laClase);
                return;
            }

            Colega obj = Activator.CreateInstance(elTipo) as Colega;

            if (obj != null)
            {
                obj.Nombre = "Pepe";
                obj.Email = "pepe@outlook.com";

                Console.WriteLine("Objeto creado correctamente: {0}{1}{2}, {3}",
                                  obj.GetType().Name, "\r\n",
                                  obj.Nombre, obj.Email);
            }
            else
            {
                Console.WriteLine("Parece que el tipo: {0} no es del tipo adecuado.", 
                                  laClase);
            }

            Console.WriteLine();
        }

        void pruebaDirecta()
        {
            var laClase = "ActivatorCS.Colega";

            Type elTipo = Type.GetType(laClase);

            Colega obj = Activator.CreateInstance(elTipo) as Colega;

            if (obj != null)
            {
                obj.Nombre = "Pepe";
                obj.Email = "pepe@outlook.com";
            }

        }

        static void Main2()
        {
            var laClase = "ActivatorVB.unColega";

            Type elTipo = Type.GetType(laClase);

            IColega obj = ((IColega)Activator.CreateInstance(elTipo));

            if (obj != null)
            {
                obj.Nombre = "Pepe";
            }
        }  

    }

    public interface IColega
    {
        string Nombre { get; set; }
    }

    public class unColega : IColega
    {
        public string Nombre { get; set; }
    }


    public class Colega
    {
        public string Nombre { get; set; }
        public string Email { get; set; }
    }

    // Clase no instanciable
    public abstract class ColegaAbstracto : Colega
    {
        public int Edad { get; set; }
    }

}

namespace OtroEspacio
{

    public class Colega
    {
        public string Nombre { get; set; }
        public int Edad { get; set; }
    }

    public class Coleguilla : ActivatorCS.Colega
    {
        public int Edad { get; set; }
    }

    // las clase selladas (sealed / NotInheritable)
    // se pueden usar, pero siempre deben tener
    // un constructor público sin parámetros
    public sealed class Coleguilla2 : ActivatorCS.Colega
    {

        //protected Coleguilla2()
        //{ 
        //}

        //private Coleguilla2()
        //{
        //}

        public int Edad { get; set; }
    }

}

 

Nos vemos.

Guillermo

Código de cómo instanciar una clase a partir del contenido de una cadena (Visual Basic)

 

Lo dicho el código completo para Visual Basic del ejemplo comentado en:

Crear un objeto a partir de una cadena con Activator.CreateInstance

 

(el enlace al de C# está en ese mismo artículo)

 

Namespace ActivatorVB

    Public NotInheritable Class CrearClase

        Public Shared Sub Main()

            'CrearClase2.Prueba()

            'Main2()

            Prueba()

            Console.ReadKey()

        End Sub

        Private Shared Sub Prueba()
            ' La clase a crear
            Dim elNombre = "ActivatorVB.Colega"

            crearColega(elNombre)

            ' Esta clase se llama igual,
            ' pero no es del mismo tipo
            ' y no pasaría la prueba de IsAssignableFrom,
            ' aunque no daría error al hacer la conversión
            ' pero no crearía una instancia,
            ' por tanto Activator devolvería nulo,
            ' en realidad el valor nulo lo devuelve
            ' la operación de conversión de tipos
            ' por eso en VB utilizo TryCast en lugar
            ' de DirectCast o CType
            elNombre = "OtroEspacio.Colega"
            crearColega(elNombre)

            ' esta clase se basa en la que queremos crear
            ' aunque esté en otro espacio de nombres
            elNombre = "OtroEspacio.Coleguilla"
            crearColega(elNombre)

            '' Esta no tiene constructor
            'elNombre = "OtroEspacio.Coleguilla2"
            'crearColega(elNombre)


            ' este tipo no existe,
            ' pero debemos usar IsAssignableFrom
            ' para no provocar una excepción
            elNombre = "Activator.Colega"
            crearColega(elNombre)

            ' esta se basa en la nuestra
            ' pero es abstracta (no tiene constructor)
            ' ya dará un error al crearla
            ' aunque pasaría la prueba de IsAssignableFrom
            Try
                elNombre = "ActivatorVB.ColegaAbstracto"
                crearColega(elNombre)

            Catch ex As Exception
                Console.WriteLine("Mrw! (o Ups!) esta clase {0} da error: {1}",
                                  elNombre, ex.Message)

            End Try

        End Sub

        Private Shared Sub crearColega(laClase As String)
            Dim elTipo As Type = Type.GetType(laClase)

            If Not GetType(Colega).IsAssignableFrom(elTipo) Then
                Console.WriteLine("El tipo: {0} no es del tipo adecuado." & vbLf & "",
                                  laClase)
                Return

            End If

            'Dim obj1 As Object = Activator.CreateInstance(elTipo)
            'Dim obj2 As Colega = CType(Activator.CreateInstance(elTipo), Colega)
            'Dim obj3 As Colega = DirectCast(Activator.CreateInstance(elTipo), Colega)

            Dim obj As Colega = TryCast(Activator.CreateInstance(elTipo), Colega)

            If obj IsNot Nothing Then
                obj.Nombre = "Pepe"
                obj.Email = "pepe@outlook.com"

                Console.WriteLine("Objeto creado correctamente: {0}{1}{2}, {3}",
                                  obj.GetType().Name, vbCrLf,
                                  obj.Nombre, obj.Email)
            Else
                Console.WriteLine("Parece que el tipo: {0} no es del tipo adecuado.",
                                  laClase)
            End If

            Console.WriteLine()
        End Sub

        Sub pruebaDirecta()
            Dim laClase = "ActivatorVB.Colega"

            Dim elTipo As Type = Type.GetType(laClase)

            Dim obj As Colega = TryCast(Activator.CreateInstance(elTipo), Colega)

            If obj IsNot Nothing Then
                obj.Nombre = "Pepe"
                obj.Email = "pepe@outlook.com"
            End If

        End Sub

        Shared Sub Main2()
            Dim laClase = "ActivatorVB.unColega"

            Dim elTipo As Type = Type.GetType(laClase)

            Dim obj As IColega = TryCast(Activator.CreateInstance(elTipo), IColega)

            If obj IsNot Nothing Then
                obj.Nombre = "Pepe"
            End If

        End Sub

    End Class

    Public Interface IColega
        Property Nombre As String
    End Interface

    Public Class unColega
        Implements IColega

        Public Property Nombre As String Implements IColega.Nombre
    End Class

    Public Class Colega
        Public Property Nombre As String
        Public Property Email As String
    End Class

    ' Clase no instanciable
    Public MustInherit Class ColegaAbstracto
        Inherits Colega

        Public Property Edad As Integer
    End Class

End Namespace

Namespace OtroEspacio

    Public Class Colega
        Public Property Nombre As String
        Public Property Edad As Integer
    End Class

    Public Class Coleguilla
        Inherits ActivatorVB.Colega

        Public Property Edad As Integer

    End Class

    ' las clase selladas (sealed / NotInheritable)
    ' se pueden usar, pero siempre deben tener 
    ' un constructor público sin parámetros
    Public NotInheritable Class Coleguilla2
        Inherits ActivatorVB.Colega

        'Protected Sub New()
        'End Sub

        'Private Sub New()
        'End Sub

        Public Property Edad As Integer
    End Class

End Namespace


 

Nos vemos.

Guillermo

P.S. (06/Ene/13)

He actualizado el código que esta entrada la edité desde el editor de WordPress y se hizo un follón, quitando los espacios y el formato… GRRRR!