Creando instancias a partir del nombre y assembly de la clase

by cristian 25. August 2009 20:15

Entre las cosas interesantes que muchos hacemos a diario (o bueno, configuramos a diario) y que muy pocas veces nos preguntamos ¿cómo lo hicieron? esta el uso de handlers o providers en la .Net Framework. Por ejemplo, muchas veces vemos algo como:

<viewStatePersisters default="cachePersister">
    <persisters>
        <add name="pagePersister" type="Rioshu.Web.ViewStateHandlers.TinyPagePersister, Rioshu.Web.ViewStateHandlers" />
        <add name="cachePersister" type="Rioshu.Web.ViewStateHandlers.WebCachePersister, Rioshu.Web.ViewStateHandlers" />
    </persisters>
</viewStatePersisters>

Y asumimos correctamente que la framework tomará esa información e instanciará el manejador o clase correspondiente que hemos indicado por su Full Qualified Name. ¿Cómo hace la framework para cargar el tipo correcto en el assembly correcto y luego instanciarlo?. La respuesta es simple, una mezcla de propiedades del tipo del objeto y a un amigo llamado “Activator”.

Cuando me refiero al “tipo del objeto” no me refiero a si es Integer, String u Object. En la .Net Framework existe un “objeto especial” cuya responsabilidad es brindar información acerca del “tipo”, este objeto es System.Type, bien, Type tiene un método especial llamado GetType, al cual podemos pasarle el Full Qualified Name de la clase y el .Net Assembly and Type Loader intentará cargarlo.

public class TypeLoaderFacts
{
    private const string ExternalTypeName = "ExternalLibrary.ExternalServiceImplementation, ExternalLibrary";
    
    [Fact]
    public void It_can_load_a_type_by_his_fqn()
    {
        var type = Type.GetType(ExternalTypeName);
        Assert.Equal(typeof(ExternalServiceImplementation), type);
    }
}

Bien, con cargar el tipo no hacemos mucho, es hora de inicializarlo.

public class TypeLoaderFacts
{
    private const string ExternalTypeName = "ExternalLibrary.ExternalServiceImplementation, ExternalLibrary";

    private Type ExternalType;
    
    public TypeLoaderFacts()
    {
        ExternalType = Type.GetType(ExternalTypeName);
    }

    [Fact]
    public void It_can_load_a_type_by_his_fqn()
    {
        Assert.Equal(typeof(ExternalServiceImplementation), ExternalType);
    }

    [Fact]
    public void It_can_ctor_a_type()
    {
        var instance = Activator.CreateInstance(ExternalType);
        Assert.NotNull(instance);
    }
}

Pero como ustedes siguen también buenas prácticas, recordaran que es buena idea programar en base a interface y no a una clase concreta, así que podemos preguntarle al tipo si implementa la clase (algo que vamos a hacer usando un pequeño método de extensión).

public class TypeLoaderFacts
{
    private const string ExternalTypeName = "ExternalLibrary.ExternalServiceImplementation, ExternalLibrary";

    private Type ExternalType;
    
    public TypeLoaderFacts()
    {
        ExternalType = Type.GetType(ExternalTypeName);
    }

    [Fact]
    public void It_can_load_a_type_by_his_fqn()
    {
        Assert.Equal(typeof(ExternalServiceImplementation), ExternalType);
    }

    [Fact]
    public void It_can_ctor_a_type()
    {
        var instance = Activator.CreateInstance(ExternalType);
        Assert.NotNull(instance);
    }

    [Fact]
    public void It_implements_our_interface()
    {
        Assert.True(ExternalType.IsImplementationOf<IExternalService>());
    }
}

Bien, les queda de tarea el averiguar como crear el extension method en cuestion :)

Como ven es sumamente fácil llegar a implementar dynamic loaders en base a un archivo de configuración de esta manera (‘ala’ web.config de asp.net o NHibernate).

Como siempre cualquier comentario estamos a un mensaje de distancia!

Tags: , , ,

.Net | ASP.NET

Comments are closed

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen

About me

Hi, My name is Cristian Prieto, I'm a Senior Software Developer living in Guatemala, Central America. I mainly "speak" in .Net languages (like C#, F# and _even_ VB.NET) but I really love programming in Python/Ruby/Erlang. When I'm not programming (or speaking at a .net user group) I enjoy reading and spend my life with my beautiful wife (Emy) and my three cats: Cocco, Motto and Chester

Recent Comments

None

Calendar

<<  December 2009  >>
MoTuWeThFrSaSu
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar