Freigeben über


Exemplarische Vorgehensweise: Erstellen und Verwenden dynamischer Objekte in C#

Dynamische Objekte machen Elemente wie Eigenschaften und Methoden zur Laufzeit statt zur Kompilierungszeit verfügbar. Mit dynamischen Objekten können Sie Objekte erstellen, um mit Strukturen zu arbeiten, die nicht mit einem statischen Typ oder Format übereinstimmen. Sie können z. B. ein dynamisches Objekt verwenden, um auf das HTML-Dokumentobjektmodell (DOM) zu verweisen, das eine beliebige Kombination aus gültigen HTML-Markupelementen und -attributen enthalten kann. Da jedes HTML-Dokument eindeutig ist, werden die Member für ein bestimmtes HTML-Dokument zur Laufzeit bestimmt. Eine gängige Methode zum Verweisen auf ein Attribut eines HTML-Elements besteht darin, den Namen des Attributs an die GetProperty Methode des Elements zu übergeben. Um auf das id Attribut des HTML-Elements <div id="Div1">zu verweisen, erhalten Sie zuerst einen Verweis auf das <div> Element, und verwenden Sie divElement.GetProperty("id")dann . Wenn Sie ein dynamisches Objekt verwenden, können Sie auf das id Attribut verweisen als divElement.id.

Dynamische Objekte bieten auch bequemen Zugriff auf dynamische Sprachen wie IronPython und IronRuby. Sie können ein dynamisches Objekt verwenden, um sich auf ein dynamisches Skript zu beziehen, das zur Laufzeit ausgeführt wird.

Sie verweisen auf ein dynamisches Objekt mithilfe einer verspäteten Bindung. Sie geben den Typ eines spät gebundenen Objekts als dynamic an. Weitere Informationen finden Sie unter dynamisch.

Sie können benutzerdefinierte dynamische Objekte mithilfe der Klassen im System.Dynamic Namespace erstellen. Sie können z. B. zur Laufzeit ein ExpandoObject erstellen und die Mitglieder dieses Objekts angeben. Sie können auch ihren eigenen Typ erstellen, der die DynamicObject Klasse erbt. Sie können die Member dieser DynamicObject-Klasse anschließend außer Kraft setzen, um dynamische Funktionen zur Laufzeit bereitzustellen.

Dieser Artikel enthält zwei voneinander unabhängige exemplarische Vorgehensweisen:

  • Erstellen Sie ein benutzerdefiniertes Objekt, das den Inhalt einer Textdatei dynamisch als Eigenschaften eines Objekts verfügbar macht.
  • Erstellen Sie ein Projekt, das eine IronPython Bibliothek verwendet.

Voraussetzungen

Hinweis

Auf Ihrem Computer werden möglicherweise unterschiedliche Namen oder Speicherorte für einige der Visual Studio-Benutzeroberflächenelemente in den folgenden Anweisungen angezeigt. Die Visual Studio-Edition, über die Sie verfügen, und die Einstellungen, die Sie verwenden, bestimmen diese Elemente. Weitere Informationen finden Sie unter Personalisierung der IDE.

  • Installieren Sie IronPython für .NET für die zweite Anleitung. Wechseln Sie zur Downloadseite , um die neueste Version zu erhalten.

Erstellen eines benutzerdefinierten dynamischen Objekts

Die erste exemplarische Vorgehensweise definiert ein benutzerdefiniertes dynamisches Objekt, das den Inhalt einer Textdatei durchsucht. Eine dynamische Eigenschaft gibt den text an, nach dem gesucht werden soll. Wenn beispielsweise der aufrufende Code angibt dynamicFile.Sample, gibt die dynamische Klasse eine generische Liste von Zeichenfolgen zurück, die alle Zeilen aus der Datei enthält, die mit "Sample" beginnen. Die Groß- und Kleinschreibung wird bei der Suche nicht berücksichtigt. Die dynamische Klasse unterstützt auch zwei optionale Argumente. Das erste Argument ist ein Enumerationswert für Suchoptionen, der angibt, dass die dynamische Klasse am Anfang der Zeile, am Ende der Zeile oder an einer beliebigen Stelle in der Zeile nach Übereinstimmungen suchen soll. Das zweite Argument gibt an, dass die dynamische Klasse vor der Suche die führenden und nachfolgenden Leerzeichen aus jeder Zeile entfernt. Wenn beispielsweise der aufrufte Code angibt dynamicFile.Sample(StringSearchOption.Contains), sucht die dynamische Klasse an einer beliebigen Stelle in einer Zeile nach "Sample". Wenn der Aufrufcode angibt dynamicFile.Sample(StringSearchOption.StartsWith, false), sucht die dynamische Klasse am Anfang jeder Zeile nach "Sample", und entfernt keine führenden und nachgestellten Leerzeichen. Das Standardverhalten der dynamischen Klasse besteht darin, am Anfang jeder Zeile nach einer Übereinstimmung zu suchen und führende und nachfolgende Leerzeichen zu entfernen.

Erstellen einer benutzerdefinierten dynamischen Klasse

Starten Sie Visual Studio. Wählen Sie Neues Projekt erstellen aus. Wählen Sie im Dialogfeld " Neues Projekt erstellen " C# und dann "Konsolenanwendung" und dann "Weiter" aus. Geben Sie im Dialogfeld "DynamicSample" den Projektnamen ein, und wählen Sie dann "Weiter" aus. Wählen Sie im Dialogfeld "Zusätzliche Informationen " .NET 7.0 (Aktuell) für das Zielframework und dann "Erstellen" aus. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das DynamicSample-Projekt, und wählen Sie"Klasse> aus. Geben Sie im ReadOnlyFile" den Namen ein, und wählen Sie dann "Hinzufügen" aus. Fügen Sie oben in der datei ReadOnlyFile.cs oder ReadOnlyFile.vb den folgenden Code hinzu, um die System.IOSystem.Dynamic Namespaces zu importieren.

using System.IO;
using System.Dynamic;

Das benutzerdefinierte dynamische Objekt verwendet eine Enumeration, um die Suchkriterien zu bestimmen. Fügen Sie vor der Klassen-Anweisung die folgende Enum-Definition hinzu.

public enum StringSearchOption
{
    StartsWith,
    Contains,
    EndsWith
}

Aktualisieren Sie die Klassen-Anweisung, um die DynamicObject Klasse zu erben, wie im folgenden Codebeispiel gezeigt.

class ReadOnlyFile : DynamicObject

Fügen Sie der ReadOnlyFile Klasse den folgenden Code hinzu, um ein privates Feld für den Dateipfad und einen Konstruktor für die ReadOnlyFile Klasse zu definieren.

// 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. Fügen Sie der GetPropertyValue Klasse die folgende ReadOnlyFile Methode hinzu. Die GetPropertyValue Methode verwendet als Eingabekriterien suchkriterien und gibt die Zeilen aus einer Textdatei zurück, die diesen Suchkriterien entsprechen. Die von der ReadOnlyFile Klasse bereitgestellten dynamischen Methoden rufen die GetPropertyValue Methode auf, um ihre jeweiligen Ergebnisse abzurufen.
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;
}

Fügen Sie nach der GetPropertyValue Methode den folgenden Code hinzu, um die TryGetMember Methode der DynamicObject Klasse außer Kraft zu setzen. Die TryGetMember Methode wird aufgerufen, wenn ein Element einer dynamischen Klasse angefordert wird und keine Argumente angegeben werden. Das binder Argument enthält Informationen zum element, auf das verwiesen wird, und das result Argument verweist auf das für das angegebene Element zurückgegebene Ergebnis. Die TryGetMember Methode gibt einen booleschen Wert zurück, der zurückgibt true , wenn das angeforderte Element vorhanden ist; andernfalls wird der Wert zurückgegeben 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;
}

Fügen Sie nach der TryGetMember Methode den folgenden Code hinzu, um die TryInvokeMember Methode der DynamicObject Klasse außer Kraft zu setzen. Die TryInvokeMember Methode wird aufgerufen, wenn ein Element einer dynamischen Klasse mit Argumenten angefordert wird. Das binder Argument enthält Informationen zum element, auf das verwiesen wird, und das result Argument verweist auf das für das angegebene Element zurückgegebene Ergebnis. Das args Argument enthält ein Array der Argumente, die an das Element übergeben werden. Die TryInvokeMember Methode gibt einen booleschen Wert zurück, der zurückgibt true , wenn das angeforderte Element vorhanden ist; andernfalls wird der Wert zurückgegeben false.

Die benutzerdefinierte Version der TryInvokeMember-Methode erwartet, dass das erste Argument ein Wert aus dem StringSearchOption-Enum ist, den Sie in einem vorherigen Schritt definiert haben. Die TryInvokeMember Methode erwartet, dass das zweite Argument ein boolescher Wert ist. Wenn ein oder beide Argumente gültige Werte sind, werden sie an die GetPropertyValue Methode übergeben, um die Ergebnisse abzurufen.

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

Speichern und schließen Sie die Datei.

Erstellen einer Beispieltextdatei

Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das DynamicSample-Projekt, und wählen Sie "Neues Element> aus. Wählen Sie im Bereich "Installierte Vorlagen " die Option "Allgemein" und dann die Textdateivorlage aus. Behalten Sie den Standardnamen von TextFile1.txt im Feld "Name " bei, und wählen Sie dann "Hinzufügen" aus. Kopieren Sie den folgenden Text in die dateiTextFile1.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

Speichern und schließen Sie die Datei.

Erstellen einer Beispielanwendung, die das benutzerdefinierte dynamische Objekt verwendet

Doppelklicken Sie im Projektmappen-Explorer auf die Program.cs Datei. Fügen Sie der Main Prozedur den folgenden Code hinzu, um eine Instanz der ReadOnlyFile Klasse für die TextFile1.txt Datei zu erstellen. Der Code verwendet späte Bindung, um dynamische Member aufzurufen und Textzeilen abzurufen, die die Zeichenfolge "Customer" enthalten.

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

Speichern Sie die Datei, und drücken Sie STRG+F5 , um die Anwendung zu erstellen und auszuführen.

Aufrufen einer dynamischen Sprachbibliothek

Die folgende exemplarische Vorgehensweise erstellt ein Projekt, das auf eine Bibliothek zugreift, die in der dynamischen Sprache IronPython geschrieben wurde.

So erstellen Sie eine benutzerdefinierte dynamische Klasse

Klicken Sie in Visual Studio auf Datei>Neu>Projekt. Wählen Sie im Dialogfeld " Neues Projekt erstellen " C# und dann "Konsolenanwendung" und dann "Weiter" aus. Geben Sie im Dialogfeld "DynamicIronPythonSample" den Projektnamen ein, und wählen Sie dann "Weiter" aus. Wählen Sie im Dialogfeld "Zusätzliche Informationen " .NET 7.0 (Aktuell) für das Zielframework und dann "Erstellen" aus. Installieren Sie das IronPython NuGet-Paket. Bearbeiten Sie die Program.cs Datei. Fügen Sie oben in der Datei den folgenden Code hinzu, um die Microsoft.Scripting.Hosting und IronPython.Hosting Namespaces aus den IronPython-Bibliotheken und den System.Linq Namespace zu importieren.

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

Fügen Sie in der Main-Methode den folgenden Code hinzu, um ein neues Microsoft.Scripting.Hosting.ScriptRuntime Objekt zum Hosten der IronPython-Bibliotheken zu erstellen. Das ScriptRuntime Objekt lädt das IronPython-Bibliotheksmodul 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.");

Fügen Sie nach dem Code zum Laden des random.py Moduls den folgenden Code hinzu, um ein Array mit ganzen Zahlen zu erstellen. Das Array wird an die shuffle Methode des random.py Moduls übergeben, das die Werte im Array zufällig sortiert.

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

Speichern Sie die Datei, und drücken Sie STRG+F5 , um die Anwendung zu erstellen und auszuführen.

Siehe auch