Visual Basic, VB .NET, ASP, ActiveX, Access, SQL Server

Criando classes com propriedades dinâmicas  

Imagine poder criar objetos cujo conjunto de propriedades possa ser modificado em tempo de execução. Não estou falando de modificar o valor das propriedades, mas de poder adicionar novas propriedades e remover antigas. Isto abre possibilidades novas para a adaptação das classes a fatores que somente são identificados em tempo de execução.

Para exemplificar como fazer isto, vamos criar um novo projeto e adicionar dois módulos de classe ao projeto. Para o primeiro módulo, configuraremos a propriedade "Name" como "CObjeto" e, para o segundo módulo, configuraremos a propriedade "Name" como "CPropriedade". Dentro do módulo de classe "CObjeto", criaremos uma propriedade somente leitura do tipo Collection chamada "Propriedades". Adicionemos o código abaixo ao módulo "CObjeto":

Private m_Propriedades As New Collection

Public Property Get Propriedades() As Collection

   Set Propriedades = m_Propriedades

End Property

Faremos da propriedade acima a propriedade padrão da classe "CObjeto". O modo de fazer isto é usar o Object Browser do VB teclando F2. Na janela do Object Browser, na combo em que se vê "All libraries" selecionado, selecione o nome do projeto. Mais abaixo, aparecerão listadas as classes "CObjeto" e "CPropriedade". Selecione a classe "CObjeto" para ver listadas à direita a propriedade "Propriedades". Clique com o botão direito sobre ela e escolha "Properties". Na janela que surgir, clique no botão "Advanced >>" e selecione "(Default)" na combo "Procedure Id". Clique em "OK" e esta passará a ser a propriedade padrão da classe "CObjeto". Como esta é uma propriedade do tipo coleção, por ser padrão da classe, você não precisará usar a sintaxe Objeto.Propriedades("...") para acessar um item adicionado à coleção "Propriedades". Bastará usar a sintaxe Objeto!Chave, onde Chave é a string usada como chave para adicionar o item à coleção "Propriedades".

Voltando ao nosso projeto, vamos adicionar o código abaixo ao módulo "CPropriedade":

Private m_Valor As Variant

Private m_Nome As String

Public Property Get Valor() As Variant

    Valor = m_Valor

End Property

Public Property Let Valor(NewValue As Variant)

    m_Valor = NewValue

End Property

Public Property Get Nome() As String

    Nome = m_Nome

End Property

Public Property Let Nome(NewValue As String)

    m_Nome = NewValue

End Property

Este código define duas propriedades para a classe "CPropriedade": "Valor" e "Nome". Do mesmo modo como fizemos acima para tornar padrão da classe "CObjeto" a propriedade "Propriedades", tornaremos padrão da classe "CPropriedade" a propriedade "Valor". Portanto, tecle F2 e repita os passos indicados acima para a propriedade "Valor" de "CPropriedade".

Uma vez realizadas as tarefas acima, no evento Form_Load do formulário do projeto, adicione o código abaixo:

Dim obj As New CObjeto, p As New CPropriedade

p.Nome = "Prop1"

p.Valor = "Valor teste"  ' ou p = "Valor teste", por "Valor" ser a propriedade padrão

obj.Propriedades.Add p, p.Nome

MsgBox obj!Prop1

obj!Prop1 = "Novo valor"

MsgBox obj!Prop1

No código acima, criamos uma instância "obj" da classe "CObjeto" e adicionamos uma propriedade "p" criada como instância da classe CPropriedade à coleção de propriedades de "obj". Usamos o nome da propriedade como chave para adicioná-la à coleção Propriedades. Como a propriedade "Propriedades" é padrão de "CObjeto", podemos acessar qualquer item adicionado à coleção com a sintaxe obj!ChaveDoItem ou obj("ChaveDoItem"). Como a propriedade "Valor" é padrão da classe "CPropriedade", ao acessar uma propriedade de "obj", temos automaticamente o valor da propriedade "Valor" retornado. Por isto o código "MsgBox obj!Prop1" mostrará "Valor teste" no primeiro caso e "Novo valor" no segundo caso.

Caso queiramos sofisticar ainda mais o exemplo, podemos criar a propriedade TipoDeDado para a classe CPropriedade e adicionar ao procedimento Let da propriedade Valor uma rotina que testa se o valor recebido pode ser convertido para o tipo de dado atribuido ao objeto CPropriedade. Não sendo possível a conversão, é gerado um erro. No caso de valores nulos serem passados, o valor Empty é atribuído à variável interna m_Valor.

Podemos também criar a propriedade "Propriedades" como uma coleção tipificada, isto é, como uma coleção de objetos do tipo "CPropriedade". Isto nos possibilitará usar blocos "For Each" para percorrer os itens da coleção. A forma mais simples de fazer isto é usar o addin "VB6 Class Builder Utility". Use-o para criar uma coleção nomeada colPropriedades e use-a como tipo de dados para a propriedade "Propriedades" da classe "CObjeto". Não esqueça de alterar o tipo Collection para colPropriedades tanto na variável m_Propriedades como no procedimento Get da propriedade.