Passo a passo: Criando e usando objetos dinâmicos no Visual Basic

Os objetos dinâmicos expõem membros como propriedades e métodos em tempo de execução, em vez de em tempo de compilação. Isso permite que você crie objetos para trabalhar com estruturas que não correspondem a um tipo ou formato estático. Por exemplo, você pode usar um objeto dinâmico para fazer referência ao DOM (Document Object Model) HTML, que pode conter qualquer combinação de elementos e atributos de marcação HTML válidos. Como cada documento HTML é exclusivo, os membros de um documento HTML específico são determinados em tempo de execução. Um método comum para fazer referência a um atributo de um elemento HTML é passar o nome do atributo para o GetProperty método do elemento . Para fazer referência ao id atributo do elemento <div id="Div1">HTML , primeiro obtenha uma referência ao <div> elemento e, em seguida, use divElement.GetProperty("id"). Se você usar um objeto dinâmico, poderá fazer referência ao id atributo como divElement.id.

Objetos dinâmicos também fornecem acesso conveniente a linguagens dinâmicas como IronPython e IronRuby. Você pode usar um objeto dinâmico para fazer referência a um script dinâmico que é interpretado em tempo de execução.

Você faz referência a um objeto dinâmico usando a associação tardia. Você especifica o tipo de um objeto de ligação tardia como Object. Para obter mais informações, consulte [Vinculação antecipada e tardia.

Você pode criar objetos dinâmicos personalizados usando as classes no System.Dynamic namespace. Por exemplo, pode criar um ExpandoObject e especificar os membros desse objeto em tempo de execução. Você também pode criar seu próprio tipo que herda a DynamicObject classe. Pode-se então substituir os membros da classe DynamicObject para fornecer funcionalidade dinâmica em tempo de execução.

Este artigo contém duas instruções passo a passo independentes:

  • Crie um objeto personalizado que exponha dinamicamente o conteúdo de um arquivo de texto como propriedades de um objeto.

  • Crie um projeto que use uma IronPython biblioteca.

Você pode fazer um destes ou ambos, e se você fizer ambos, a ordem não importa.

Pré-requisitos

Nota

Seu computador pode mostrar nomes ou locais diferentes para alguns dos elementos da interface do usuário do Visual Studio nas instruções a seguir. A edição do Visual Studio que você tem e as configurações que você usa determinam esses elementos. Para obter mais informações, consulte Personalizando o IDE.

  • Para o segundo passo a passo, instale o IronPython para .NET. Vá para a página de download para obter a versão mais recente.

Criar um objeto dinâmico personalizado

O primeiro passo a passo define um objeto dinâmico personalizado que pesquisa o conteúdo de um arquivo de texto. Uma propriedade dinâmica especifica o texto a ser pesquisado. Por exemplo, se o código de chamada especificar dynamicFile.Sample, a classe dinâmica retornará uma lista genérica de cadeias de caracteres que contém todas as linhas do arquivo que começam com "Sample". A pesquisa não diferencia maiúsculas de minúsculas. A classe dinâmica também suporta dois argumentos opcionais. O primeiro argumento é um valor enum da opção de pesquisa que especifica que a classe dinâmica deve procurar correspondências no início da linha, no final da linha ou em qualquer lugar da linha. O segundo argumento especifica que a classe dinâmica deve cortar espaços à esquerda e à direita de cada linha antes de pesquisar. Por exemplo, se o código de chamada especificar dynamicFile.Sample(StringSearchOption.Contains), a classe dinâmica procurará "Exemplo" em qualquer lugar de uma linha. Se o código de chamada especificar dynamicFile.Sample(StringSearchOption.StartsWith, false), a classe dinâmica procurará "Exemplo" no início de cada linha e não removerá espaços à esquerda e à direita. O comportamento padrão da classe dinâmica é procurar uma correspondência no início de cada linha e remover espaços à esquerda e à direita.

Para criar uma classe dinâmica personalizada

  1. Inicie o Visual Studio.

  2. Selecione Criar um novo projeto.

  3. Na caixa de diálogo Criar um novo projeto, selecione Visual Basic, selecione Aplicativo de Console e selecione Avançar.

  4. Na caixa de diálogo Configurar seu novo projeto, digite DynamicSample o nome do projeto e selecione Avançar.

  5. Na caixa de diálogo Informações adicionais, selecione .NET 5.0 (Atual) para o Target Framework e, em seguida, selecione Criar.

    O novo projeto é criado.

  6. No Explorador de Soluções, clique com o botão direito no projeto DynamicSample e selecione Adicionar>Classe. Na caixa Nome, digite ReadOnlyFilee selecione Adicionar.

    É adicionado um novo arquivo que contém a classe ReadOnlyFile.

  7. Na parte superior do arquivo ReadOnlyFile.cs ou ReadOnlyFile.vb , adicione o código a seguir para importar os System.IO namespaces e System.Dynamic .

    Imports System.IO
    Imports System.Dynamic
    
  8. O objeto dinâmico personalizado usa um enum para determinar os critérios de pesquisa. Antes da instrução class, adicione a seguinte definição de enum.

    Public Enum StringSearchOption
        StartsWith
        Contains
        EndsWith
    End Enum
    
  9. Atualize a instrução class para herdar a DynamicObject classe, conforme mostrado no exemplo de código a seguir.

    Public Class ReadOnlyFile
        Inherits DynamicObject
    
  10. Adicione o seguinte código à ReadOnlyFile classe para definir um campo privado para o caminho do arquivo e um construtor para a ReadOnlyFile classe.

    ' Store the path to the file and the initial line count value.
    Private p_filePath As String
    
    ' Public constructor. Verify that file exists and store the path in 
    ' the private variable.
    Public Sub New(ByVal filePath As String)
        If Not File.Exists(filePath) Then
            Throw New Exception("File path does not exist.")
        End If
    
        p_filePath = filePath
    End Sub
    
  11. Adicione o seguinte método GetPropertyValue à classe ReadOnlyFile. O GetPropertyValue método toma, como entrada, critérios de pesquisa e retorna as linhas de um arquivo de texto que correspondem a esse critério de pesquisa. Os métodos dinâmicos fornecidos pela ReadOnlyFile classe chamam o GetPropertyValue método para recuperar seus respetivos resultados.

    Public Function GetPropertyValue(ByVal propertyName As String,
                                     Optional ByVal StringSearchOption As StringSearchOption = StringSearchOption.StartsWith,
                                     Optional ByVal trimSpaces As Boolean = True) As List(Of String)
    
        Dim sr As StreamReader = Nothing
        Dim results As New List(Of String)
        Dim line = ""
        Dim testLine = ""
    
        Try
            sr = New StreamReader(p_filePath)
    
            While Not sr.EndOfStream
                line = sr.ReadLine()
    
                ' Perform a case-insensitive search by using the specified search options.
                testLine = UCase(line)
                If trimSpaces Then testLine = Trim(testLine)
    
                Select Case StringSearchOption
                    Case StringSearchOption.StartsWith
                        If testLine.StartsWith(UCase(propertyName)) Then results.Add(line)
                    Case StringSearchOption.Contains
                        If testLine.Contains(UCase(propertyName)) Then results.Add(line)
                    Case StringSearchOption.EndsWith
                        If testLine.EndsWith(UCase(propertyName)) Then results.Add(line)
                End Select
            End While
        Catch
            ' Trap any exception that occurs in reading the file and return Nothing.
            results = Nothing
        Finally
            If sr IsNot Nothing Then sr.Close()
        End Try
    
        Return results
    End Function
    
  12. Após o método GetPropertyValue, adicione o código a seguir para sobrepor o método TryGetMember da classe DynamicObject. O TryGetMember método é chamado quando um membro de uma classe dinâmica é solicitado e nenhum argumento é especificado. O binder argumento contém informações sobre o membro referenciado e faz result referência ao resultado retornado para o membro especificado. O TryGetMember método retorna um valor booleano que retorna true se o membro solicitado existir, caso contrário, ele retorna false.

    ' Implement the TryGetMember method of the DynamicObject class for dynamic member calls.
    Public Overrides Function TryGetMember(ByVal binder As GetMemberBinder,
                                           ByRef result As Object) As Boolean
        result = GetPropertyValue(binder.Name)
        Return If(result Is Nothing, False, True)
    End Function
    
  13. Após o método TryGetMember, adicione o código a seguir para sobrescrever o método TryInvokeMember da classe DynamicObject. O TryInvokeMember método é chamado quando um membro de uma classe dinâmica é solicitado com argumentos. O binder argumento contém informações sobre o membro referenciado e faz result referência ao resultado retornado para o membro especificado. O args argumento contém uma matriz dos argumentos que são passados para o membro. O TryInvokeMember método retorna um valor booleano que retorna true se o membro solicitado existir, caso contrário, ele retorna false.

    A versão personalizada do TryInvokeMember método espera que o primeiro argumento seja um valor do StringSearchOption enum que você definiu em uma etapa anterior. O TryInvokeMember método espera que o segundo argumento seja um valor booleano. Se um ou ambos os argumentos forem valores válidos, eles serão passados para o GetPropertyValue método para recuperar os resultados.

    ' Implement the TryInvokeMember method of the DynamicObject class for 
    ' dynamic member calls that have arguments.
    Public Overrides Function TryInvokeMember(ByVal binder As InvokeMemberBinder,
                                              ByVal args() As Object,
                                              ByRef result As Object) As Boolean
    
        Dim StringSearchOption As StringSearchOption = StringSearchOption.StartsWith
        Dim trimSpaces = True
    
        Try
            If args.Length > 0 Then StringSearchOption = CType(args(0), StringSearchOption)
        Catch
            Throw New ArgumentException("StringSearchOption argument must be a StringSearchOption enum value.")
        End Try
    
        Try
            If args.Length > 1 Then trimSpaces = CType(args(1), Boolean)
        Catch
            Throw New ArgumentException("trimSpaces argument must be a Boolean value.")
        End Try
    
        result = GetPropertyValue(binder.Name, StringSearchOption, trimSpaces)
    
        Return If(result Is Nothing, False, True)
    End Function
    
  14. Guarde e feche o ficheiro.

Para criar um arquivo de texto de exemplo

  1. No Explorador de Soluções, clique com o botão direito no projeto DynamicSample e selecione Adicionar>Novo Item. No painel Modelos Instalados, selecione Geral, e, em seguida, selecione o modelo Arquivo de Texto. Deixe o nome padrão de TextFile1.txt na caixa Nome e clique em Adicionar. Um novo arquivo de texto é adicionado ao projeto.

  2. Copie o seguinte texto para o ficheiro TextFile1.txt .

    List of customers and suppliers
    
    Supplier: Lucerne Publishing (https://www.lucernepublishing.com/)
    Customer: Preston, Chris
    Customer: Hines, Patrick
    Customer: Cameron, Maria
    Supplier: Graphic Design Institute (https://www.graphicdesigninstitute.com/)
    Supplier: Fabrikam, Inc. (https://www.fabrikam.com/)
    Customer: Seubert, Roxanne
    Supplier: Proseware, Inc. (http://www.proseware.com/)
    Customer: Adolphi, Stephan
    Customer: Koch, Paul
    
  3. Guarde e feche o ficheiro.

Para criar um aplicativo de exemplo que usa o objeto dinâmico personalizado

  1. No Gerenciador de Soluções, clique duas vezes no arquivo Program.vb .

  2. Adicione o seguinte código ao Main procedimento para criar uma instância da ReadOnlyFile classe para o arquivo TextFile1.txt . O código utiliza a vinculação tardia para invocar membros dinâmicos e recuperar linhas de texto que contêm a sequência de caracteres "Cliente".

    Dim rFile As Object = New ReadOnlyFile("..\..\..\TextFile1.txt")
    For Each line In rFile.Customer
        Console.WriteLine(line)
    Next
    Console.WriteLine("----------------------------")
    For Each line In rFile.Customer(StringSearchOption.Contains, True)
        Console.WriteLine(line)
    Next
    
  3. Salve o arquivo e pressione Ctrl+F5 para criar e executar o aplicativo.

Chamar uma biblioteca de linguagem dinâmica

O passo a passo a seguir cria um projeto que acessa uma biblioteca escrita na linguagem dinâmica IronPython.

Para criar uma classe dinâmica personalizada

  1. No Visual Studio, selecione Arquivo>Novo>Projeto.

  2. Na caixa de diálogo Criar um novo projeto, selecione Visual Basic, selecione Aplicativo de Console e selecione Avançar.

  3. Na caixa de diálogo Configurar seu novo projeto, digite DynamicIronPythonSample o nome do projeto e selecione Avançar.

  4. Na caixa de diálogo Informações adicionais, selecione .NET 5.0 (Atual) para o Target Framework e, em seguida, selecione Criar.

    O novo projeto é criado.

  5. Instale o pacote NuGet do IronPython .

  6. Edite o arquivo Program.vb .

  7. Na parte superior do arquivo, adicione o código a seguir para importar os namespaces Microsoft.Scripting.Hosting e IronPython.Hosting das bibliotecas IronPython e o namespace System.Linq.

    Imports Microsoft.Scripting.Hosting
    Imports IronPython.Hosting
    Imports System.Linq
    
  8. No método Main, adicione o código a seguir para criar um novo Microsoft.Scripting.Hosting.ScriptRuntime objeto para hospedar as bibliotecas IronPython. O ScriptRuntime objeto carrega o módulo de biblioteca IronPython random.py.

    ' Set the current directory to the IronPython libraries.
    System.IO.Directory.SetCurrentDirectory(
        Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) &
           "\IronPython 2.7\Lib")
    
    ' Create an instance of the random.py IronPython library.
    Console.WriteLine("Loading random.py")
    Dim py = Python.CreateRuntime()
    Dim random As Object = py.UseFile("random.py")
    Console.WriteLine("random.py loaded.")
    
  9. Após o código para carregar o módulo random.py, adicione o código a seguir para criar uma matriz de inteiros. A matriz é passada para o shuffle método do módulo random.py, que classifica aleatoriamente os valores na matriz.

    ' Initialize an enumerable set of integers.
    Dim items = Enumerable.Range(1, 7).ToArray()
    
    ' Randomly shuffle the array of integers by using IronPython.
    For i = 0 To 4
        random.shuffle(items)
        For Each item In items
            Console.WriteLine(item)
        Next
        Console.WriteLine("-------------------")
    Next
    
  10. Salve o arquivo e pressione Ctrl+F5 para criar e executar o aplicativo.

Consulte também