Escrito em April 8th, 2009 as 7:46 am por Guilherme Bacellar

3 Comentários

Iremos começar a utilizar reflexão, para tanto, vamos adotar uma classe modelo para que possamos ter controle sobre a utilização:

C#

namespace ReflectionCSharp
{
    /// <summary>
    /// Classe de Usuário de Exemplo
    /// </summary>
    [Serializable]
    [XmlRoot("Usuário")]
    public class Usuario : System.Object, IComparable<Usuario>, INotifyPropertyChanged
    {
        #region Construtores

        public Usuario() { }

        public Usuario(string nome, int idade, DateTime dataNascimento)
        {
            _Nome = nome;
            _Idade = idade;
            _DataNascimento = dataNascimento;
        }

        #endregion

        #region Fields (Campos)

        private string _Nome;
        private int _Idade;
        private DateTime _DataNascimento;

        #endregion

        #region Propriedades

        [XmlAttribute("Nome")]
        public string Nome
        {
            get { return _Nome; }
            set { _Nome = value; }
        }

        public int Idade
        {
            get { return _Idade; }
            set { _Idade = value; }
        }

        [XmlElement("DataNascimento")]
        public DateTime DataNascimento
        {
            get { return _DataNascimento; }
            set { _DataNascimento = value; }
        }

        #endregion

        #region Eventos

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Implementações dos Métodos das Interfaces Declaradas

        /// <summary>
        /// Método da Interface IComparable
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int CompareTo(Usuario other)
        {
            // Realiza Comparação de Nome
            return this.Nome.CompareTo(other.Nome);
        }

        #endregion

        #region Métodos

        /// <summary>
        /// Calcula a Idade do Usuário pela Data do Nascimento
        /// </summary>
        /// <returns></returns>
        public int CalculaIdade()
        {
            // Chama o Método Privado Estático desta Classe
            return CalculaIdade(this.DataNascimento);
        }

        /// <summary>
        /// Calcula a Idade do Usuário pela Data do Nascimento passada por Parâmetro
        /// </summary>
        /// <returns></returns>
        private static int CalculaIdade(DateTime dataNascimento)
        {
            TimeSpan result = DateTime.Now.Subtract(dataNascimento);
            return (int)(result.TotalDays / 365);
        }

        #endregion
    }
}

VB.Net

Namespace ReflectionVBNet

''' <summary>
''' Classe de Usuário de Exemplo
''' </summary>
''' <remarks></remarks>
<Serializable()> _
<XmlRoot("Usuário")> _
Public Class Usuario
Implements INotifyPropertyChanged, IComparable(Of Usuario)

    #Region "Construtores"

    Public Sub New()

    End Sub

    Public Sub New(ByVal nome As String, ByVal idade As Int32, ByVal dataNascimento As DateTime)
        _Nome = nome
        _Idade = idade
        _DataNascimento = dataNascimento
    End Sub

    #End Region

    #Region "Fields (Campos)"

    Private _Nome As String
    Private _Idade As Integer
    Private _DataNascimento As DateTime

    #End Region

    #Region "Propriedades"

    <XmlAttribute("Nome")> _
    Public Property Nome() As String
    Get
        Return _Nome
    End Get
    Set(ByVal value As String)
        _Nome = value
    End Set
    End Property

    Public Property Idade() As Integer
    Get
        Return _Idade
    End Get
    Set(ByVal value As Integer)
        _Idade = value
    End Set
    End Property

    <XmlElement("DataNascimento")> _
    Public Property DataNascimento() As Date
    Get
        Return _DataNascimento
    End Get
    Set(ByVal value As Date)
        _DataNascimento = value
    End Set
    End Property
    #End Region

    #Region "Eventos"

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    #End Region

    #Region "Implementações dos Métodos das Interfaces Declaradas"

    ''' <summary>
    ''' Método da Interface IComparable
    ''' </summary>
    ''' <param name="other"></param>
    Public Function CompareTo(ByVal other As Usuario) As Integer Implements IComparable(Of Usuario).CompareTo
        Return Me.Nome.CompareTo(other.Nome)
    End Function

    #End Region

    #Region "Métodos"

    ''' <summary>
    ''' Calcula a Idade do Usuário pela Data do Nascimento
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CalculaIdade() As Integer
        '' Chama o Método Privado Estático desta Classe
        Return CalculaIdade(Me.DataNascimento)
    End Function

    ''' <summary>
    ''' Calcula a Idade do Usuário pela Data do Nascimento passada por Parâmetro
    ''' </summary>
    ''' <remarks></remarks>
    Private Function CalculaIdade(ByVal dataNascimento As DateTime) As Integer
        Dim result As TimeSpan = DateTime.Now.Subtract(dataNascimento)
        Return CType((result.TotalDays / 365), Int32)
    End Function

    #End Region

    End Class
End Namespace

Essa classe foi criada para que possamos trabalhar de forma controlada com Reflection e também foi desenhada para conter todos os itens que podemos precisar para nosso estudo sobre Reflection.

Recuperando todos os Construtores

A recuperação de construtores com Reflection permite que possamos criar as instâncias de nossos objetos utilizando os recursos já implementados nos construtores.

Para tanto, utilizaremos o método (GetConstructors) do tipo desejado.

C#

// Cria Objetos
Type meuTipo;
ConstructorInfo[] constructors;

// Recupera o Tipo Desejado
meuTipo = typeof(Usuario);

// Recupera os Construtores
constructors = meuTipo.GetConstructors();

VB.Net

' Cria Objetos
Dim meuTipo As Type
Dim constructors As ConstructorInfo()

' Recupera o Tipo Desejado
meuTipo = GetType(Usuario)

' Recupera os Construtores
constructors = meuTipo.GetConstructors()

Desta forma temos uma coleção dos construtores que definem nosso objeto. Neste caso, nossa classe (Usuario) possui 2 construtores.

Recuperando um (01) Construtor Específico

Na maioria das situações precisaremos recuperar apenas 1 construtor específico e não todos eles.
Neste caso, utilizamos o método (GetConstructor) do tipo desejado.

C#

// Cria Objetos
Type meuTipo;
ConstructorInfo parameterLessConstructor;
ConstructorInfo parameterizedConstructor;

// Recupera o Tipo Desejado
meuTipo = typeof(Usuario);

// Recupera o Construtor sem Parâmetros
parameterLessConstructor = meuTipo.GetConstructor(new Type[]{});

// Recupera o Construtor com o Nome (string), Idade (int) e Data do Nascimento (DateTime)
parameterizedConstructor = meuTipo.GetConstructor(new Type[] {typeof (string), typeof (int), typeof (DateTime)});

VB.Net

' Cria Objetos
Dim meuTipo As Type
Dim parameterLessConstructor As ConstructorInfo
Dim parameterizedConstructor As ConstructorInfo

' Recupera o Tipo Desejado
meuTipo = GetType(Usuario)

' Recupera o Construtor sem Parâmetros
parameterLessConstructor = meuTipo.GetConstructor(New Type() {})

' Recupera o Construtor com o Nome (String), Idade (Integer) e Data do Nascimento (DateTime)
parameterizedConstructor = meuTipo.GetConstructor(New Type() {GetType(String), GetType(Integer), GetType(DateTime)})

Perceba que, o método (GetConstructor) “como quase todos os métodos que recuperam informações por Reflection” responde a assinatura do elemento desejado.

Então, em nosso caso, passando-se uma lista de “Tipos” vazia temos como resposta um Construtor sem parâmetros. Mas, se passarmos uma lista de “Tipos” os “Tipos” dos parâmetros obteremos de retorno o elemento que atende à assinatura dos “Tipos” especificados.

Esse conceito é muito importante na Reflexão, então, vamos guardá-lo.

E se os Construtores não forem Públicos?

Até agora está tudo fácil, mas, e se o construtor não for público?

Se por acaso, o construtor de nosso objeto (Usuario) não fosse público, o método acima retornaria nulo/nothing como resultado da recuperação do construtor.

Contudo, o mecanismo de Reflexão do .NET é extremamente poderoso e permite que recuperaremos membros “não públicos” dos objetos.

C#

// Cria Objetos
Type meuTipo;
ConstructorInfo parameterLessConstructor;

// Recupera o Tipo Desejado
meuTipo = typeof(Usuario);

// Recupera o Construtor sem Parâmetros
parameterLessConstructor = meuTipo.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[]{}, null);

VB.Net

' Cria Objetos
Dim meuTipo As Type
Dim parameterLessConstructor As ConstructorInfo

' Recupera o Tipo Desejado
meuTipo = GetType(Usuario)

' Recupera o Construtor sem Parâmetros
parameterLessConstructor = meuTipo.GetConstructor(BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, New Type() {}, Nothing)

Observemos o método (GetConstructor) com mais parâmetros. Dentre eles existem as BindingFlags, que permitem a mudança do escopo da Reflexão. Em nosso exemplo estamos pedindo por membros “não públicos” e “de instância”.

Observe os outros parâmetros nulos. Eles são para especificar-mos um “Binder” customizado, e modificadores de parâmetros. Não vamos entrar neles neste momento, mas, em breve vamos explicar-los em detalhes.
Sendo assim, obtemos um construtor sem parâmetros (observem o “Tipo” vazio) e que ao mesmo tempo é privado.

Este também é outro conceito muito importante do mecanismo de Reflection.

Construindo Classes

Bom, tudo isso para que possamos construir uma classe, então, vamos lá.
Nosso objeto “ConstructorInfo” contém um método chamado “Invoke” que ativa seu funcionamento, então….

C#

// Cria Objetos
Usuario novoUsuarioSemParametros;
Usuario novoUsuarioComParametros;

// Cria Novo Usuário com o Construtor sem os Parâmetros
novoUsuarioSemParametros = (Usuario)parameterLessConstructor.Invoke(null);

// Cria um Novo Usuário com o Contrutor com os 3 Parâmetros
novoUsuarioComParametros = (Usuario)parameterizedConstructor.Invoke(new object[] { "Guilherme Bacellar Moralez", 25, new DateTime(1982, 10, 12) });

VB.Net

' Cria Objetos
Dim novoUsuarioSemParametros As Usuario
Dim novoUsuarioComParametros As Usuario

' Cria Novo Usuário com o Construtor sem os Parâmetros
novoUsuarioSemParametros = CType(parameterLessConstructor.Invoke(Nothing), Usuario)

' Cria um Novo Usuário com o Contrutor com os 3 Parâmetros
novoUsuarioComParametros = CType(parameterizedConstructor.Invoke(New Object() {"Guilherme Bacellar Moralez", 25, New DateTime(1982, 10, 12)}), Usuario)

Conseguimos criar novos objetos (Usuario) com o construtor sem parâmetros e com o construtor com parâmetros.

Para finalizar, observe que o método (Invoke) recebe uma coleção de (Objetos) com os parâmetros desejados para a ativação do construtor.

Bom, de Construtores com Reflexão é só.

Posts Relacionados:

  1. Reflection – Parte 4 (Propriedades)
  2. Reflection – Parte 3 (Fields)
  3. Reflection – Parte 5 (Interfaces)
  4. Tipos Nulos (Nullable Value Types)
  5. Por Dentro das Propriedades Automáticas
  6. Ordenação de Listas (Coleções)
  7. Introdução a Reflection
, , , , ,

3 Respostas to “Reflection Parte 2 – Construtores”

3 Trackbacks For This Post

  1. Reflection - Parte 3 (Fields) | .Net Max Says:

    [...] Para este post, será necessário a utilização da classe (Usuario) descrita no post (Reflection Parte 2 – Construtores) [...]

  2. Reflection - Parte 4 (Propriedades) | .Net Max Says:

    [...] Para este post, será necessário a utilização da classe (Usuario) descrita no post (Reflection Parte 2 – Construtores) [...]

  3. Reflection - Parte 5 (Interfaces) | .Net Max Says:

    [...] Para este post, será necessário a utilização da classe (Usuario) descrita no post (Reflection Parte 2 – Construtores) [...]

Deixa uma Resposta

znjdb32s6g