Share via


Overzicht: Dynamische objecten maken en gebruiken in C#

Dynamische objecten stellen leden beschikbaar, zoals eigenschappen en methoden tijdens runtime, in plaats van tijdens het compileren. Met dynamische objecten kunt u objecten maken om te werken met structuren die niet overeenkomen met een statisch type of een statische indeling. U kunt bijvoorbeeld een dynamisch object gebruiken om te verwijzen naar het HTML Document Object Model (DOM), dat elke combinatie van geldige HTML-opmaakelementen en -kenmerken kan bevatten. Omdat elk HTML-document uniek is, worden de leden voor een bepaald HTML-document tijdens de runtime bepaald. Een veelgebruikte methode om te verwijzen naar een kenmerk van een HTML-element is door de naam van het kenmerk door te geven aan de GetProperty methode van het element. Als u wilt verwijzen naar het id kenmerk van het HTML-element <div id="Div1">, verkrijgt u eerst een verwijzing naar het <div> element en gebruikt u divElement.GetProperty("id")vervolgens . Als u een dynamisch object gebruikt, kunt u verwijzen naar het id kenmerk als divElement.id.

Dynamische objecten bieden ook handige toegang tot dynamische talen, zoals IronPython en IronRuby. U kunt een dynamisch object gebruiken om te verwijzen naar een dynamisch script dat tijdens runtime wordt geïnterpreteerd.

U verwijst naar een dynamisch object met behulp van late binding. U geeft het type van een te laat gebonden object op als dynamic. Zie dynamisch voor meer informatie.

U kunt aangepaste dynamische objecten maken met behulp van de klassen in de System.Dynamic naamruimte. U kunt bijvoorbeeld een ExpandoObject object maken en de leden van dat object opgeven tijdens runtime. U kunt ook uw eigen type maken waarmee de DynamicObject klasse wordt overgenomen. Vervolgens kunt u de leden van de DynamicObject klasse overschrijven om dynamische runtimefunctionaliteit te bieden.

Dit artikel bevat twee onafhankelijke scenario's:

  • Maak een aangepast object waarmee de inhoud van een tekstbestand dynamisch wordt weergegeven als eigenschappen van een object.
  • Maak een project dat gebruikmaakt van een IronPython bibliotheek.

Vereisten

Notitie

Mogelijk worden op uw computer verschillende namen of locaties weergegeven voor sommige elementen van de Visual Studio-gebruikersinterface in de volgende instructies. De Visual Studio-editie die u hebt en de instellingen die u gebruikt, bepalen deze elementen. Zie Personalizing the IDE (Personalizing the IDE) voor meer informatie.

Een aangepast dynamisch object maken

In het eerste overzicht wordt een aangepast dynamisch object gedefinieerd waarmee de inhoud van een tekstbestand wordt doorzocht. Met een dynamische eigenschap geeft u de tekst op die moet worden gezocht. Als u bijvoorbeeld code aanroept, retourneert dynamicFile.Samplede dynamische klasse een algemene lijst met tekenreeksen die alle regels uit het bestand bevatten dat begint met 'Voorbeeld'. De zoekopdracht is niet hoofdlettergevoelig. De dynamische klasse ondersteunt ook twee optionele argumenten. Het eerste argument is een opsommingswaarde voor zoekopties die aangeeft dat de dynamische klasse moet zoeken naar overeenkomsten aan het begin van de regel, het einde van de regel of ergens in de regel. Het tweede argument geeft aan dat de dynamische klasse voorloop- en volgspaties van elke regel moet knippen voordat u zoekt. Als u bijvoorbeeld code aanroept dynamicFile.Sample(StringSearchOption.Contains), zoekt de dynamische klasse ergens in een regel naar Voorbeeld. Als u code aanroept dynamicFile.Sample(StringSearchOption.StartsWith, false), zoekt de dynamische klasse aan het begin van elke regel naar 'Sample' en worden voorloop- en volgspaties niet verwijderd. Het standaardgedrag van de dynamische klasse is het zoeken naar een overeenkomst aan het begin van elke regel en het verwijderen van voorloop- en volgspaties.

Een aangepaste dynamische klasse maken

Start Visual Studio. Selecteer Een nieuw project maken. Selecteer in het dialoogvenster Een nieuw project maken de optie C#, selecteer Consoletoepassing en selecteer vervolgens Volgende. Voer in het dialoogvenster Uw nieuwe project configureren de naam van het project in DynamicSample en selecteer vervolgens Volgende. Selecteer in het dialoogvenster Aanvullende informatie .NET 7.0 (huidig) voor het doelframework en selecteer vervolgens Maken. Klik in Solution Explorer met de rechtermuisknop op het DynamicSample-project en selecteer Klasse toevoegen>. Typ in het vak Naam en selecteer Vervolgens Toevoegen.ReadOnlyFile Voeg boven aan het bestand ReadOnlyFile.cs of ReadOnlyFile.vb de volgende code toe om de System.IO en System.Dynamic naamruimten te importeren.

using System.IO;
using System.Dynamic;

Het aangepaste dynamische object gebruikt een enum om de zoekcriteria te bepalen. Voeg vóór de klasse-instructie de volgende enumdefinitie toe.

public enum StringSearchOption
{
    StartsWith,
    Contains,
    EndsWith
}

Werk de klasse-instructie bij om de DynamicObject klasse over te nemen, zoals wordt weergegeven in het volgende codevoorbeeld.

class ReadOnlyFile : DynamicObject

Voeg de volgende code toe aan de ReadOnlyFile klasse om een privéveld voor het bestandspad en een constructor voor de ReadOnlyFile klasse te definiëren.

// 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;
}
  1. Voeg de volgende methode GetPropertyValue toe aan de klasse ReadOnlyFile. De GetPropertyValue methode gebruikt, als invoer, zoekcriteria en retourneert de regels uit een tekstbestand dat overeenkomt met die zoekcriteria. De dynamische methoden die door de ReadOnlyFile klasse worden geleverd, roepen de GetPropertyValue methode aan om hun respectieve resultaten op te halen.
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;
}

Voeg na de GetPropertyValue methode de volgende code toe om de TryGetMember methode van de DynamicObject klasse te overschrijven. De TryGetMember methode wordt aangeroepen wanneer een lid van een dynamische klasse wordt aangevraagd en er geen argumenten worden opgegeven. Het binder argument bevat informatie over het lid waarnaar wordt verwezen en het result argument verwijst naar het resultaat dat is geretourneerd voor het opgegeven lid. De TryGetMember methode retourneert een Booleaanse waarde die retourneert true als het aangevraagde lid bestaat; anders wordt deze geretourneerd false.

// 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;
}

Voeg na de TryGetMember methode de volgende code toe om de TryInvokeMember methode van de DynamicObject klasse te overschrijven. De TryInvokeMember methode wordt aangeroepen wanneer een lid van een dynamische klasse wordt aangevraagd met argumenten. Het binder argument bevat informatie over het lid waarnaar wordt verwezen en het result argument verwijst naar het resultaat dat is geretourneerd voor het opgegeven lid. Het args argument bevat een matrix van de argumenten die worden doorgegeven aan het lid. De TryInvokeMember methode retourneert een Booleaanse waarde die retourneert true als het aangevraagde lid bestaat; anders wordt deze geretourneerd false.

In de aangepaste versie van de TryInvokeMember methode wordt verwacht dat het eerste argument een waarde is van de StringSearchOption enum die u in een vorige stap hebt gedefinieerd. De TryInvokeMember methode verwacht dat het tweede argument een Booleaanse waarde is. Als een of beide argumenten geldige waarden zijn, worden deze doorgegeven aan de GetPropertyValue methode om de resultaten op te halen.

// 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;
}

Sla het bestand op en sluit het bestand.

Een voorbeeldtekstbestand maken

Klik in Solution Explorer met de rechtermuisknop op het DynamicSample-project en selecteer Nieuw item toevoegen>. Selecteer Algemeen in het deelvenster Geïnstalleerde sjablonen en selecteer vervolgens de sjabloon Tekstbestand. Laat de standaardnaam van TextFile1.txt in het vak Naam staan en selecteer Vervolgens Toevoegen. Kopieer de volgende tekst naar het TextFile1.txt-bestand .

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

Sla het bestand op en sluit het bestand.

Een voorbeeldtoepassing maken die gebruikmaakt van het aangepaste dynamische object

Dubbelklik in Solution Explorer op het Program.cs-bestand . Voeg de volgende code toe aan de Main procedure om een exemplaar van de ReadOnlyFile klasse voor het TextFile1.txt-bestand te maken. De code maakt gebruik van late binding om dynamische leden aan te roepen en regels tekst op te halen die de tekenreeks 'Klant' bevatten.

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);
}

Sla het bestand op en druk op Ctrl+F5 om de toepassing te bouwen en uit te voeren.

Een dynamische taalbibliotheek aanroepen

In het volgende scenario wordt een project gemaakt dat toegang heeft tot een bibliotheek die is geschreven in de dynamische taal IronPython.

Een aangepaste dynamische klasse maken

Selecteer in Visual Studio Bestand>Nieuw>Project. Selecteer in het dialoogvenster Een nieuw project maken de optie C#, selecteer Consoletoepassing en selecteer vervolgens Volgende. Voer in het dialoogvenster Uw nieuwe project configureren de naam van het project in DynamicIronPythonSample en selecteer vervolgens Volgende. Selecteer in het dialoogvenster Aanvullende informatie .NET 7.0 (huidig) voor het doelframework en selecteer vervolgens Maken. Installeer het IronPython NuGet-pakket. Bewerk het Program.cs bestand. Voeg boven aan het bestand de volgende code toe om de Microsoft.Scripting.Hosting en IronPython.Hosting naamruimten uit de IronPython-bibliotheken en de System.Linq naamruimte te importeren.

using System.Linq;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;

Voeg in de Main-methode de volgende code toe om een nieuw Microsoft.Scripting.Hosting.ScriptRuntime object te maken om de IronPython-bibliotheken te hosten. Het ScriptRuntime object laadt de IronPython-bibliotheekmodule 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");
ScriptRuntime py = Python.CreateRuntime();
dynamic random = py.UseFile("random.py");
Console.WriteLine("random.py loaded.");

Nadat de code voor het laden van de random.py-module is uitgevoerd, voegt u de volgende code toe om een matrix met gehele getallen te maken. De matrix wordt doorgegeven aan de shuffle methode van de random.py-module, waarmee de waarden in de matrix willekeurig worden gesorteerd.

// 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("-------------------");
}

Sla het bestand op en druk op Ctrl+F5 om de toepassing te bouwen en uit te voeren.

Zie ook