Genomgång: Skapa och använda dynamiska objekt i Visual Basic

Dynamiska objekt tillgängliggör medlemmar, till exempel egenskaper och metoder vid körningstidpunkt, i stället för vid kompileringstidpunkt. På så sätt kan du skapa objekt som fungerar med strukturer som inte matchar en statisk typ eller ett statiskt format. Du kan till exempel använda ett dynamiskt objekt för att referera till HTML-dokumentobjektmodellen (DOM), som kan innehålla valfri kombination av giltiga HTML-markeringselement och attribut. Eftersom varje HTML-dokument är unikt, bestäms komponenterna för det specifika HTML-dokumentet vid körningstid. En vanlig metod för att referera till ett attribut för ett HTML-element är att skicka namnet på attributet till GetProperty -metoden för elementet. Om du vill referera id till attributet för HTML-elementet <div id="Div1">hämtar du först en referens till elementet <div> och använder divElement.GetProperty("id")sedan . Om du använder ett dynamiskt objekt kan du referera till id attributet som divElement.id.

Dynamiska objekt ger också bekväm åtkomst till dynamiska språk som IronPython och IronRuby. Du kan använda ett dynamiskt objekt för att referera till ett dynamiskt skript som tolkas vid körning.

Du refererar till ett dynamiskt objekt med hjälp av sen bindning. Du anger typen av ett sent bundet objekt som Object. Mer information finns i [Tidig och Sen bindning.

Du kan skapa anpassade dynamiska objekt med hjälp av klasserna i System.Dynamic namnområdet. Du kan till exempel skapa en ExpandoObject och ange objektets medlemmar under körning. Du kan också skapa en egen typ som ärver DynamicObject klassen. Du kan sedan åsidosätta medlemmarna i klassen DynamicObject för att tillhandahålla dynamisk funktionalitet vid körning.

Den här artikeln innehåller två oberoende genomgångar:

  • Skapa ett anpassat objekt som dynamiskt exponerar innehållet i en textfil som egenskaper för ett objekt.

  • Skapa ett projekt som använder ett IronPython bibliotek.

Du kan göra antingen en av dessa eller båda, och om du gör båda, spelar ordningen ingen roll.

Förutsättningar

Kommentar

Datorn kan visa olika namn eller platser för vissa av Visual Studio-användargränssnittselementen i följande instruktioner. Den Visual Studio-utgåva som du har och de inställningar som du använder avgör dessa element. Mer information finns i Anpassa IDE.

  • För den andra genomgången installerar du IronPython för .NET. Gå till nedladdningssidan för att hämta den senaste versionen.

Skapa ett anpassat dynamiskt objekt

Den första genomgången definierar ett anpassat dynamiskt objekt som söker i innehållet i en textfil. En dynamisk egenskap anger den text som ska sökas efter. Om anropande kod till exempel anger returnerar dynamicFile.Sampleden dynamiska klassen en allmän lista med strängar som innehåller alla rader från filen som börjar med "Exempel". Sökningen är inte skiftlägeskänslig. Den dynamiska klassen stöder också två valfria argument. Det första argumentet är ett uppräkningsvärde för sökalternativ som anger att den dynamiska klassen ska söka efter matchningar i början av raden, slutet av raden eller var som helst på raden. Det andra argumentet anger att den dynamiska klassen ska trimma inledande och avslutande blanksteg från varje rad innan den söker. Om anropande kod anger dynamicFile.Sample(StringSearchOption.Contains) till exempel söker den dynamiska klassen efter "Sample" var som helst i raden. Om anropskoden anger dynamicFile.Sample(StringSearchOption.StartsWith, false), söker den dynamiska klassen efter "Sample" i början av varje rad och tar inte bort inledande och avslutande blanksteg. Standardbeteendet för den dynamiska klassen är att söka efter en matchning i början av varje rad och ta bort inledande och avslutande blanksteg.

Skapa en anpassad dynamisk klass

  1. Starta Visual Studio.

  2. Välj Skapa ett nytt projekt.

  3. I dialogrutan Skapa ett nytt projekt väljer du Visual Basic, konsolprogram och sedan Nästa.

  4. I dialogrutan Konfigurera det nya projektet anger du DynamicSample som Projektnamn och väljer sedan Nästa.

  5. I dialogrutan Ytterligare information väljer du .NET 5.0 (aktuell) för Target Framework och väljer sedan Skapa.

    Det nya projektet skapas.

  6. Högerklicka på Projektet DynamicSample i Solution Explorer och välj Lägg till>klass. I rutan Namn skriver du ReadOnlyFileoch väljer sedan Lägg till.

    En ny fil läggs till som innehåller klassen ReadOnlyFile.

  7. Överst i filen ReadOnlyFile.cs eller ReadOnlyFile.vb lägger du till följande kod för att importera System.IO namnrymderna och System.Dynamic .

    Imports System.IO
    Imports System.Dynamic
    
  8. Det anpassade dynamiska objektet använder en enum för att fastställa sökkriterier. Lägg till följande uppräkningsdefinition före klassdeklarationen.

    Public Enum StringSearchOption
        StartsWith
        Contains
        EndsWith
    End Enum
    
  9. Uppdatera klass-instruktionen DynamicObject för att ärva klassen, enligt följande kodexempel.

    Public Class ReadOnlyFile
        Inherits DynamicObject
    
  10. Lägg till följande kod i ReadOnlyFile klassen för att definiera ett privat fält för filsökvägen och en konstruktor för ReadOnlyFile klassen.

    ' 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. Lägg till följande GetPropertyValue-metod i klassen ReadOnlyFile. Metoden GetPropertyValue tar, som indata, sökvillkor och returnerar raderna från en textfil som matchar sökvillkoren. De dynamiska metoder som tillhandahålls av ReadOnlyFile klassen anropar GetPropertyValue metoden för att hämta respektive resultat.

    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. GetPropertyValue Efter metoden lägger du till följande kod för att åsidosätta TryGetMember -metoden för DynamicObject klassen. Metoden TryGetMember anropas när en medlem i en dynamisk klass begärs och inga argument anges. Argumentet binder innehåller information om den refererade medlemmen och result argumentet refererar till resultatet som returneras för den angivna medlemmen. Metoden TryGetMember returnerar ett booleskt värde som returnerar true om den begärda medlemmen finns. Annars returneras 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. TryGetMember Efter metoden lägger du till följande kod för att åsidosätta TryInvokeMember -metoden för DynamicObject klassen. Metoden TryInvokeMember anropas när en medlem i en dynamisk klass begärs med argument. Argumentet binder innehåller information om den refererade medlemmen och result argumentet refererar till resultatet som returneras för den angivna medlemmen. Argumentet args innehåller en matris med argumenten som skickas till medlemmen. Metoden TryInvokeMember returnerar ett booleskt värde som returnerar true om den begärda medlemmen finns. Annars returneras false.

    Den anpassade versionen av TryInvokeMember metoden förväntar sig att det första argumentet är ett värde från den StringSearchOption uppräkning som du definierade i ett tidigare steg. Metoden TryInvokeMember förväntar sig att det andra argumentet är ett booleskt värde. Om ett eller båda argumenten är giltiga värden skickas de till GetPropertyValue metoden för att hämta resultatet.

    ' 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. Spara och stäng filen.

Så här skapar du en exempeltextfil

  1. Högerklicka på Projektet DynamicSample i Solution Explorer och välj Lägg till>nytt objekt. I fönstret Installerade mallar väljer du Allmänt och sedan mallen Textfil . Lämna standardnamnet för TextFile1.txt i rutan Namn och klicka sedan på Lägg till. En ny textfil läggs till i projektet.

  2. Kopiera följande text till filen 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. Spara och stäng filen.

Skapa ett exempelprogram som använder det anpassade dynamiska objektet

  1. Dubbelklicka på filen Program.vb i Solution Explorer.

  2. Lägg till följande kod i proceduren Main för att skapa en instans av ReadOnlyFile klassen för TextFile1.txt-filen. Koden använder sen bindning för att anropa dynamiska medlemmar och hämta textrader som innehåller strängen "Kund".

    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. Spara filen och tryck på Ctrl+F5 för att skapa och köra programmet.

Anropa ett dynamiskt språkbibliotek

Följande genomgång skapar ett projekt som kommer åt ett bibliotek som är skrivet på det dynamiska språket IronPython.

Skapa en anpassad dynamisk klass

  1. Välj Arkiv>Nytt>Projekt i Visual Studio.

  2. I dialogrutan Skapa ett nytt projekt väljer du Visual Basic, konsolprogram och sedan Nästa.

  3. I dialogrutan Konfigurera det nya projektet anger du DynamicIronPythonSample som Projektnamn och väljer sedan Nästa.

  4. I dialogrutan Ytterligare information väljer du .NET 5.0 (aktuell) för Target Framework och väljer sedan Skapa.

    Det nya projektet skapas.

  5. Installera NuGet-paketet IronPython.

  6. Redigera filen Program.vb .

  7. Överst i filen lägger du till följande kod för att importera Microsoft.Scripting.Hosting och IronPython.Hosting namnrymder från IronPython-biblioteken samt System.Linq namnrymden.

    Imports Microsoft.Scripting.Hosting
    Imports IronPython.Hosting
    Imports System.Linq
    
  8. I main-metoden lägger du till följande kod för att skapa ett nytt Microsoft.Scripting.Hosting.ScriptRuntime objekt som ska vara värd för IronPython-biblioteken. Objektet ScriptRuntime läser in modulen random.py från IronPythons bibliotek.

    ' 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. Efter koden som läser in modulen random.py, lägg till följande kod för att skapa en array med heltal. Matrisen skickas till shuffle metoden för modulen random.py, som slumpmässigt sorterar värdena i matrisen.

    ' 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. Spara filen och tryck på Ctrl+F5 för att skapa och köra programmet.

Se även