Compartilhar via


Demonstra Passo a passo: Criando e usando objetos dinâmicos (C# e Visual Basic)

Objetos dinâmicos exponham membros como, por exemplo, propriedades e métodos em tempo de execução, em vez de em tempo de compilação. Isso lhe permite criar objetos para trabalhar com estruturas que não correspondem a um formato ou tipo estático. Por exemplo, você pode usar um objeto dinâmico para fazer referência a HTML documento objeto DOM (modelo), que pode conter qualquer combinação de atributos e elementos de marcação HTML válidos. Como cada documento HTML é exclusivo, os membros de um determinado documento HTML 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 o método do elemento. A referência a id atributo do elemento HTML <div id="Div1">, você primeiro obtém uma referência para o <div> elemento e use divElement.GetProperty("id"). Se você usar um objeto dinâmico, você pode fazer referência a id atributo como divElement.id.

Objetos dinâmicos também fornecem acesso conveniente às linguagens dinâmicas como, por exemplo, IronPython e IronRuby. Você pode usar um objeto dinâmico para se referir a um script dinâmico que é interpretado em tempo de execução.

Referência a um objeto dinâmico usando a ligação tardia. No C#, você especificar o tipo de um objeto de ligação tardia, como dynamic. Em Visual Basic, especifique o tipo de um objeto de ligação tardia, como Object. Para obter mais informações, consulte dinâmico (referência de TRANSLATION FROM VPE FOR CSHARP) e Associação inicial e tardia (Visual Basic).

Você pode criar objetos dinâmicos personalizados usando as classes de System.Dynamic namespace. Por exemplo, você pode criar um ExpandoObject e especifique os membros desse objeto em tempo de execução. Você também pode criar seu próprio tipo que herda de DynamicObject classe. Em seguida, você pode substituir os membros do DynamicObject classe para fornecer funcionalidade dinâmica em tempo de execução.

Esta explicação passo a passo você executará as seguintes tarefas:

  • Crie um objeto personalizado expõe dinamicamente o conteúdo de um arquivo de texto como propriedades de um objeto.

  • Criar um projeto que usa um IronPython biblioteca.

Pré-requisitos

Você precisa de IronPython 2.6.1 para.NET 4.0 para concluir este passo a passo. Você pode baixar o IronPython 2.6.1 para.NET 4.0 da CodePlex.

ObservaçãoObservação

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ê possui e as configurações que você usa determinam esses elementos. Para obter mais informações, consulte Configurações do Visual Studio.

Criando um objeto dinâmico de personalizado

O primeiro projeto que você criar nesta explicação define um objeto personalizado dinâmico que pesquisa o conteúdo de um arquivo de texto. Texto a ser pesquisado é especificado pelo nome de uma propriedade dinâmica. Por exemplo, se o código de chamada especifica dynamicFile.Sample, a classe dinâmica retorna uma lista genérica de seqüências 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 oferece suporte a dois argumentos opcionais. O primeiro argumento é um valor de enumeração de opção de pesquisa que especifica que a classe dinâmica deve procurar correspondente ao início da linha, no final da linha ou em qualquer lugar na linha. O segundo argumento especifica que a classe dinâmica deve aparar espaços à esquerda e de cada linha antes de pesquisar. Por exemplo, se o código de chamada especifica dynamicFile.Sample(StringSearchOption.Contains), as pesquisas de classe dinâmica de "Sample" em qualquer lugar em uma linha. Se o código de chamada especifica dynamicFile.Sample(StringSearchOption.StartsWith, false), as pesquisas de classe dinâmica de "Sample" no início de cada linha e não remover à esquerda e espaços. O comportamento padrão da classe dinâmica é procurar uma correspondência no início de cada linha e remover espaços à esquerda e.

Para criar uma classe dinâmica personalizada

  1. Inicie o Visual Studio

  2. No menu File, aponte para New e clique Project.

  3. No Novo projeto na caixa de Tipos de projeto painel, certifique-se de que Windows está selecionada. Selecione Aplicativo de Console na modelos de painel. No nome , digite DynamicSamplee em seguida, clique em OK. O novo projeto é criado.

  4. Clique com o botão direito no projeto DynamicSample e aponte para Adde em seguida, clique em classe. No nome , digite ReadOnlyFilee em seguida, clique em OK. Adicionado um novo arquivo que contém a classe ReadOnlyFile.

  5. Na parte superior do arquivo ReadOnlyFile.cs ou ReadOnlyFile.vb, adicione o seguinte código para importar o System.IO e System.Dynamic namespaces.

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

    Public Enum StringSearchOption
        StartsWith
        Contains
        EndsWith
    End Enum
    
    public enum StringSearchOption
    {
        StartsWith,
        Contains,
        EndsWith
    }
    
  7. Atualizar a declaração de classe para herdar de DynamicObject classe, conforme mostrado no seguinte exemplo de código.

    Public Class ReadOnlyFile
        Inherits DynamicObject
    
    class ReadOnlyFile : DynamicObject
    
  8. Adicione o seguinte código para o ReadOnlyFile classe para definir um campo privado para o caminho do arquivo e um construtor para o 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
    
    // Store the path to the file and the initial line count value.
    private string p_filePath;
    
    // Public constructor. Verify that file exists and store the path in 
    // the private variable.
    public ReadOnlyFile(string filePath)
    {
        if (!File.Exists(filePath))
        {
            throw new Exception("File path does not exist.");
        }
    
        p_filePath = filePath;
    }
    
  9. Adicione o seguinte GetPropertyValue método para o ReadOnlyFile classe. O GetPropertyValue método utiliza, como entrada, critérios de pesquisa e retorna as linhas a partir de um texto de arquivos que coincidirem com o que pesquisar critérios. Os métodos dinâmicos fornecidos pelo ReadOnlyFile classe chamada a GetPropertyValue método para recuperar seus respectivos 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
    
    public List<string> GetPropertyValue(string propertyName,
                                         StringSearchOption StringSearchOption = StringSearchOption.StartsWith,
                                         bool trimSpaces = true) 
    {
        StreamReader sr = null;
        List<string> results = new List<string>();
        string line = "";
        string testLine = "";
    
        try
        {
            sr = new StreamReader(p_filePath);
    
            while (!sr.EndOfStream)
            {
                line = sr.ReadLine();
    
                // Perform a case-insensitive search by using the specified search options.
                testLine = line.ToUpper();
                if (trimSpaces) { testLine = testLine.Trim(); }
    
                switch (StringSearchOption)
                {
                    case StringSearchOption.StartsWith:
                        if (testLine.StartsWith(propertyName.ToUpper())) { results.Add(line); }
                        break;
                    case StringSearchOption.Contains:
                        if (testLine.Contains(propertyName.ToUpper())) { results.Add(line); }
                        break;
                    case StringSearchOption.EndsWith:
                        if (testLine.EndsWith(propertyName.ToUpper())) { results.Add(line); }
                        break;
                }
            }
        }
        catch
        {
            // Trap any exception that occurs in reading the file and return null.
            results = null;
        }
        finally
        {
            if (sr != null) {sr.Close();}
        }
    
        return results;
    }
    
  10. Após a GetPropertyValue método, adicione o seguinte código para substituir o TryGetMember método o DynamicObject classe. O TryGetMember método é chamado quando um membro de uma classe dinâmica é solicitado e nenhum argumento for especificado. O binder argumento contém informações sobre o membro referenciado e o result argumento faz referência o resultado retornado para o membro especificado. O TryGetMember método retorna um valor booleano que retorna true se o membro solicitado existe; Caso contrário 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
    
    // Implement the TryGetMember method of the DynamicObject class for dynamic member calls.
    public override bool TryGetMember(GetMemberBinder binder,
                                      out object result) 
    {
        result = GetPropertyValue(binder.Name);
        return result == null ? false : true;
    }
    
  11. Após a TryGetMember método, adicione o seguinte código para substituir o TryInvokeMember método o DynamicObject classe. 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 o result argumento faz referência o resultado retornado para o membro especificado. O args argumento contém uma matriz de argumentos que são passados para o membro. O TryInvokeMember método retorna um valor booleano que retorna true se o membro solicitado existe; Caso contrário retorna false.

    A versão personalizada do TryInvokeMember método espera o primeiro argumento para ser um valor da StringSearchOption enum que você definiu na etapa anterior. O TryInvokeMember método espera o segundo argumento para ser um valor booleano. Se um ou ambos os argumentos são os valores válidos, eles sã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
    
    // Implement the TryInvokeMember method of the DynamicObject class for 
    // dynamic member calls that have arguments.
    public override bool TryInvokeMember(InvokeMemberBinder binder,
                                         object[] args,
                                         out object result)
    {
        StringSearchOption StringSearchOption = StringSearchOption.StartsWith;
        bool trimSpaces = true;
    
        try
        {
            if (args.Length > 0) { StringSearchOption = (StringSearchOption)args[0]; }
        }
        catch
        {
            throw new ArgumentException("StringSearchOption argument must be a StringSearchOption enum value.");
        }
    
        try
        {
            if (args.Length > 1) { trimSpaces = (bool)args[1]; }
        }
        catch
        {
            throw new ArgumentException("trimSpaces argument must be a Boolean value.");
        }
    
        result = GetPropertyValue(binder.Name, StringSearchOption, trimSpaces);
    
        return result == null ? false : true;
    }
    
  12. Salve e feche o arquivo.

Para criar um arquivo de texto de exemplo

  1. Clique com o botão direito no projeto DynamicSample e aponte para Adde em seguida, clique em Novo Item. No Modelos instalados painel, selecione Gerale selecione o O arquivo de texto modelo. Deixe o nome padrão TextFile1. txt no nome caixa e clique Add. Um novo arquivo de texto é adicionado ao projeto.

  2. Copie o seguinte texto no arquivo TextFile1. txt.

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

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

  1. Em Solution Explorer, duas vezes no arquivo de Module1. vb, se você estiver usando Visual Basic ou o arquivo Program. cs se você estiver usando Visual C#.

  2. Adicione o seguinte código ao procedimento principal para criar uma instância de ReadOnlyFile classe para o arquivo TextFile1. txt. O código usa a ligação tardia chamam membros dinâmicos e recuperar linhas de texto que contêm a seqüê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
    
    dynamic rFile = new ReadOnlyFile(@"..\..\TextFile1.txt");
    foreach (string line in rFile.Customer)
    {
        Console.WriteLine(line);
    }
    Console.WriteLine("----------------------------");
    foreach (string line in rFile.Customer(StringSearchOption.Contains, true))
    {
        Console.WriteLine(line);
    }
    
  3. Salve o arquivo e pressione CTRL + F5 para compilar e executar o aplicativo.

Chamando uma biblioteca de linguagem dinâmica

O próximo projeto que você criar nesta explicação acessa uma biblioteca que está escrita na linguagem dinâmica IronPython. Antes de criar este projeto, você deve ter o IronPython 2.6.1 para.NET 4.0 instalado. Você pode baixar o IronPython 2.6.1 para.NET 4.0 da CodePlex.

Para criar uma classe dinâmica personalizada

  1. Em Visual Studio, no menu File, aponte para New e então clique em Project.

  2. No Novo projeto na caixa de Tipos de projeto painel, certifique-se de que Windows está selecionada. Selecione Aplicativo de Console na modelos de painel. No nome , digite DynamicIronPythonSamplee em seguida, clique em OK. O novo projeto é criado.

  3. Se você estiver usando Visual Basic, o botão direito do mouse no projeto DynamicIronPythonSample e em Propriedades. Clique na aba References. Clique no botão Add. Se você estiver usando Visual C#, em Solution Explorer, com o botão direito do referências pasta e clique Adicionar referência de.

  4. Sobre o Procurar guia, navegue até a pasta onde as bibliotecas da IronPython estão instaladas. Por exemplo, C:\Program Files\IronPython 2.6 para.NET 4.0. Selecione o IronPython.dll, IronPython.Modules.dll, Microsoft.Scripting.dll, e Microsoft.Dynamic.dll bibliotecas. Clique em OK.

  5. Se você estiver usando Visual Basic, edite o arquivo de Module1. Se você estiver usando o Visual C#, edite o arquivo Program. cs.

  6. Na parte superior do arquivo, adicione o seguinte código para importar o Microsoft.Scripting.Hosting e IronPython.Hosting namespaces do IronPython bibliotecas.

    Imports Microsoft.Scripting.Hosting
    Imports IronPython.Hosting
    
    using Microsoft.Scripting.Hosting;
    using IronPython.Hosting;
    
  7. No método Main, adicione o seguinte código para criar uma nova Microsoft.Scripting.Hosting.ScriptRuntime o objeto para hospedar a bibliotecas da IronPython. O ScriptRuntime objeto carrega IronPython biblioteca módulo random.py.

    ' Set the current directory to the IronPython libraries.
    My.Computer.FileSystem.CurrentDirectory = 
       My.Computer.FileSystem.SpecialDirectories.ProgramFiles &
       "\IronPython 2.6 for .NET 4.0\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.")
    
    // Set the current directory to the IronPython libraries.
    System.IO.Directory.SetCurrentDirectory(
       Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + 
       @"\IronPython 2.6 for .NET 4.0\Lib");
    
    // Create an instance of the random.py IronPython library.
    Console.WriteLine("Loading random.py");
    ScriptRuntime py = Python.CreateRuntime();
    dynamic random = py.UseFile("random.py");
    Console.WriteLine("random.py loaded.");
    
  8. Após o código para carregar o módulo de random.py, adicione o seguinte código para criar uma matriz de inteiros. A matriz é passada para o shuffle o método do módulo random.py, aleatoriamente, que classifica 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
    
    // Initialize an enumerable set of integers.
    int[] items = Enumerable.Range(1, 7).ToArray();
    
    // Randomly shuffle the array of integers by using IronPython.
    for (int i = 0; i < 5; i++)
    {
        random.shuffle(items);
        foreach (int item in items)
        {
            Console.WriteLine(item);
        }
        Console.WriteLine("-------------------");
    }
    
  9. Salve o arquivo e pressione CTRL + F5 para compilar e executar o aplicativo.

Consulte também

Referência

System.Dynamic

System.Dynamic.DynamicObject

dinâmico (referência de TRANSLATION FROM VPE FOR CSHARP)

Conceitos

Associação inicial e tardia (Visual Basic)

Outros recursos

Novo Walkthroughs (C# e Visual Basic)