Utilizando Reflection com C#

Postado por Carlos Fernando Sylverio | Postado em Programação, Tecnologia | Postado em 08-11-2009

0

Entre as utilização de reflection podemos citar a instânciação de classes ou a utilização de plugins (como os utilizados no firefox), que são definidos em tempo de execução.

Basicamente reflection é uma maneira de se descobrir dados de uma classe/objeto/interface em tempo de execução. Dessa forma podemos examinar os tipos em um assembly e interagir com eles ou instanciá-los. Também podemos criar tipos no momento de execução.

Neste post criarei um exemplo de instânciar objetos em tempo de execução (runtime) utilizando reflection.
Abaixo segue um diagrama de classe do modelo utilizado para o exemplo:

modelo produto

Utilizando reflection

using System;
using System.Collections.Generic;
using System.Reflection;
 
namespace UtilizandoReflection {
    public class Program {
        public static void Main(string[] args) {
 
            StateFactory factory = new StateFactory();
 
            // Cria 3 produtos em estado diferentes
            Product product1 = new Product();
            Product product2 = new Product();
            Product product3 = new Product();
 
            product1.State = factory.Create(1, "item pendente");
            product2.State = factory.Create(2, "item no estoque");
            product3.State = factory.Create(3, "item vendido");
 
            Console.WriteLine("Produto {0}: {1} -- Type {2}", product1.State.ID, product1.State.Description, product1.State.GetType().ToString());
            Console.WriteLine("Produto {0}: {1} -- Type {2}", product2.State.ID, product2.State.Description, product2.State.GetType().ToString());
            Console.WriteLine("Produto {0}: {1} -- Type {2}", product3.State.ID, product3.State.Description, product3.State.GetType().ToString());
        }
    }
 
    /// <summary>Classe responsável por criar intâncias de estado</summary>
    public class StateFactory {
        private Dictionary<int, string> states;
 
        public StateFactory(){
            states = new Dictionary<int, string>(3);
            states.Add(1, "Pending");
            states.Add(2, "Stock");
            states.Add(3, "Sold");
        }
 
        /// <summary>Cria uma instância de estado</summary>
        /// <param name="ID">Identificador da instância</param>
        /// <param name="description">descrição do estado</param>
        /// <returns>Estado</returns>
        public State Create(int ID, string description) {
 
            string baseName = "UtilizandoReflection";
 
            // cria array com os parâmetro utilizado no construtor do estado
            object[] args = new object[2];
            args.SetValue(ID, 0);
            args.SetValue(description, 1);
 
            //using System.Reflection
            Assembly assembly = Assembly.Load(baseName);
            return (State)assembly.CreateInstance(baseName + "." + states[ID], true, BindingFlags.CreateInstance, null, args, null, null);
        }
    }
 
    #region Domain
    public class Product {
        public State State;
    }
    public abstract class State {
        public int ID;
        public string Description;
        public State(int ID, string description) {
            this.ID = ID;
            this.Description = description;
        }
    }
    public class Pending : State { // estado pendente
        public Pending(int ID, string description) : base(ID, description) { }
    }
    public class Stock : State { // estado estoque
        public Stock(int ID, string description) : base(ID, description) { }
    }
    public class Sold : State { // estado vendido
        public Sold(int ID, string description) : base(ID, description) { }
    }
    #endregion
}

Resultado da execução:

Produto 1: item pendente -- Type UtilizandoReflection.Pending
Produto 2: item no estoque -- Type UtilizandoReflection.Stock
Produto 3: item vendido -- Type UtilizandoReflection.Sold

Observe que as classes a serem instanciadas por reflection estão na mesma solution ou project, assim utilizamos o método Load do Assembly, porem quando a classe a ser utilizada for de uma DLL, utilizamos o método LoadFile e informamos o nome completo da DLL.

Como mencionado no início do post, há outras utilizações de reflection, como manipular atributos e métodos, mas isso é assunto para um próximo post.

Enjoy ;-)