Bagikan melalui


Panduan: Membuat dan Menggunakan Objek Dinamis di C#

Objek dinamis mengekspos anggota seperti properti dan metode saat durasi, bukan pada waktu kompilasi. Objek dinamis memungkinkan Anda membuat objek untuk bekerja dengan struktur yang tidak cocok dengan jenis atau format statis. Misalnya, Anda dapat menggunakan objek dinamis untuk mereferensikan Model Objek Dokumen (DOM) HTML, yang dapat berisi kombinasi elemen dan atribut markup HTML yang valid. Karena setiap dokumen HTML adalah unik, anggota untuk dokumen HTML tertentu ditentukan saat durasi. Metode umum untuk mereferensikan atribut elemen HTML adalah dengan meneruskan nama atribut ke metode GetProperty elemen. Untuk mereferensikan atribut id dari elemen HTML <div id="Div1">, Anda terlebih dahulu mendapatkan referensi ke elemen <div>, kemudian menggunakan divElement.GetProperty("id"). Jika Anda menggunakan objek dinamis, Anda dapat mereferensikan atribut id sebagai divElement.id.

Objek dinamis juga memberikan akses mudah ke bahasa dinamis seperti IronPython dan IronRuby. Anda dapat menggunakan objek dinamis untuk merujuk ke skrip dinamis yang ditafsirkan pada waktu proses.

Anda mereferensikan objek dinamis dengan menggunakan pengikatan akhir. Anda menentukan jenis objek yang terlambat terikat sebagai dynamic. Untuk informasi selengkapnya, lihat dinamis.

Anda dapat membuat objek dinamis kustom dengan menggunakan kelas di namespace layanan System.Dynamic. Misalnya, Anda dapat membuat ExpandoObject dan menentukan anggota objek tersebut saat durasi. Anda juga dapat membuat jenis Anda sendiri yang mewarisi kelas DynamicObject. Anda kemudian dapat mengambil alih anggota kelas DynamicObject untuk memberikan fungsionalitas dinamis run-time.

Artikel ini berisi dua panduan independen:

  • Membuat objek kustom yang secara dinamis mengekspos isi file teks sebagai properti objek.
  • Membuat proyek yang menggunakan pustaka IronPython.

Prasyarat

Catatan

Komputer Anda mungkin memperlihatkan nama atau lokasi yang berbeda untuk beberapa elemen antarmuka pengguna Visual Studio dalam petunjuk berikut. Edisi Visual Studio yang Anda miliki dan setelan yang Anda gunakan menentukan elemen-elemen ini. Untuk informasi selengkapnya, lihat Mempersonalisasi IDE.

Membuat Objek Dinamis Kustom

Panduan pertama menentukan objek dinamis kustom yang mencari isi file teks. Properti dinamis menentukan teks yang akan dicari. Misalnya, jika kode panggilan menentukan dynamicFile.Sample, kelas dinamis mengembalikan daftar string generik yang berisi semua baris dari file yang dimulai dengan "Sampel". Pencarian tidak peka huruf besar/kecil. Kelas dinamis juga mendukung dua argumen opsional. Argumen pertama adalah nilai enum opsi pencarian yang menentukan bahwa kelas dinamis harus mencari kecocokan di awal baris, akhir baris, atau di mana pun dalam baris. Argumen kedua menentukan bahwa kelas dinamis harus memangkas spasi awal dan akhir dari setiap baris sebelum mencari. Misalnya, jika kode panggilan menentukan dynamicFile.Sample(StringSearchOption.Contains), kelas dinamis mencari "Sampel" di mana pun dalam satu baris. Jika kode panggilan menentukan dynamicFile.Sample(StringSearchOption.StartsWith, false), kelas dinamis mencari "Sampel" di awal setiap baris, dan tidak menghapus spasi di awal dan belakang. Perilaku default kelas dinamis adalah mencari kecocokan di awal setiap baris dan menghapus spasi awal dan akhir.

Membuat kelas dinamis kustom

Mulai Visual Studio. Pilih Buat proyek baru. Dalam dialog Buat proyek baru, pilih C#, pilih Aplikasi Konsol, lalu pilih Berikutnya. Dalam dialog Konfigurasikan proyek baru Anda, masukkan DynamicSample untuk Nama proyek, lalu pilih Berikutnya. Dalam dialog Informasi tambahan, pilih .NET 7.0 (Saat Ini) untuk Kerangka Kerja Target, lalu pilih Buat. Di Penjelajah Solusi, klik kanan proyek DynamicSample dan pilih Tambahkan>Kelas. Dalam kotak Nama, ketik ReadOnlyFile, lalu pilih Tambahkan. Di bagian atas file ReadOnlyFile.cs atau ReadOnlyFile.vb, tambahkan kode berikut untuk mengimpor namespace layanan System.IO dan System.Dynamic.

using System.IO;
using System.Dynamic;

Objek dinamis kustom menggunakan enum untuk menentukan kriteria pencarian. Sebelum pernyataan kelas, tambahkan definisi enum berikut.

public enum StringSearchOption
{
    StartsWith,
    Contains,
    EndsWith
}

Perbarui pernyataan kelas untuk mewarisi kelas DynamicObject, seperti yang ditunjukkan pada contoh kode berikut.

class ReadOnlyFile : DynamicObject

Tambahkan kode berikut ke kelas ReadOnlyFile untuk menentukan bidang privat untuk jalur file dan konstruktor untuk kelas ReadOnlyFile.

// 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. Menambahkan metode GetPropertyValue berikut ke kelas ReadOnlyFile. Metode GetPropertyValue mengambil, sebagai input, kriteria pencarian dan mengembalikan baris dari file teks yang cocok dengan kriteria pencarian tersebut. Metode dinamis yang disediakan oleh kelas ReadOnlyFile memanggil metode GetPropertyValue untuk mengambil hasil masing-masing.
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;
}

Setelah metode GetPropertyValue, tambahkan kode berikut untuk mengganti metode TryGetMember dari kelas DynamicObject. Metode TryGetMember dipanggil saat anggota kelas dinamis diminta dan tidak ada argumen yang ditentukan. Argumen binder berisi informasi tentang anggota yang direferensikan, dan argumen result mereferensikan hasil yang dikembalikan untuk anggota yang ditentukan. Metode TryGetMember mengembalikan nilai Boolean yang mengembalikan true jika anggota yang diminta ada; jika tidak, metode tersebut mengembalikan 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;
}

Setelah metode TryGetMember, tambahkan kode berikut untuk mengganti metode TryInvokeMember dari kelas DynamicObject. Metode TryInvokeMember dipanggil saat anggota kelas dinamis diminta dengan argumen. Argumen binder berisi informasi tentang anggota yang direferensikan, dan argumen result mereferensikan hasil yang dikembalikan untuk anggota yang ditentukan. Argumen args berisi array argumen yang diteruskan ke anggota. Metode TryInvokeMember mengembalikan nilai Boolean yang mengembalikan true jika anggota yang diminta ada; jika tidak, metode tersebut mengembalikan false.

Versi kustom dari metode TryInvokeMember mengharapkan argumen pertama berupa nilai dari enum StringSearchOption yang Anda tentukan di langkah sebelumnya. Metode TryInvokeMember mengharapkan argumen kedua menjadi nilai Boolean. Jika satu atau kedua argumen adalah nilai yang valid, argumen tersebut diteruskan ke GetPropertyValue metode untuk mengambil hasilnya.

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

Simpan dan tutup file.

Membuat file teks sampel

Di Penjelajah Solusi, klik kanan proyek DynamicSample dan pilih Tambahkan>Item Baru. Di panel Templat Terinstal, pilih Umum, lalu pilih templat File Teks. Biarkan nama default TextFile1.txt dalam kotak Nama , lalu pilih Tambahkan. Salin teks berikut ke file 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

Simpan dan tutup file.

Membuat aplikasi sampel yang menggunakan objek dinamis kustom

Di Penjelajah Solusi, klik dua kali file Program.cs. Tambahkan kode berikut ke prosedur Main untuk membuat instans kelas ReadOnlyFile untuk file TextFile1.txt. Kode menggunakan pengikatan akhir untuk memanggil anggota dinamis dan mengambil baris teks yang berisi string "Pelanggan".

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

Simpan file dan tekan Ctrl+F5 untuk membuat dan menjalankan aplikasi.

Memanggil pustaka bahasa dinamis

Panduan berikut membuat proyek yang mengakses pustaka yang ditulis dalam bahasa dinamis IronPython.

Untuk membuat kelas dinamis kustom

Di Visual Studio, pilih File>Baru>Proyek. Dalam dialog Buat proyek baru, pilih C#, pilih Aplikasi Konsol, lalu pilih Berikutnya. Dalam dialog Konfigurasikan proyek baru Anda, masukkan DynamicIronPythonSample untuk Nama proyek, lalu pilih Berikutnya. Dalam dialog Informasi tambahan, pilih .NET 7.0 (Saat Ini) untuk Kerangka Kerja Target, lalu pilih Buat. Instal paket NuGet IronPython. Edit file Program.cs. Di bagian atas file, tambahkan kode berikut untuk mengimpor namespace layanan Microsoft.Scripting.Hosting dan IronPython.Hosting dari pustaka IronPython dan namespace layanan System.Linq.

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

Dalam metode Utama, tambahkan kode berikut untuk membuat objek Microsoft.Scripting.Hosting.ScriptRuntime baru untuk menghosting pustaka IronPython. Objek ScriptRuntime memuat modul pustaka 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");
ScriptRuntime py = Python.CreateRuntime();
dynamic random = py.UseFile("random.py");
Console.WriteLine("random.py loaded.");

Setelah kode untuk memuat modul random.py, tambahkan kode berikut untuk membuat array bilangan bulat. Array diteruskan ke metode shuffle dari modul random.py, yang secara acak mengurutkan nilai dalam array.

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

Simpan file dan tekan Ctrl+F5 untuk membuat dan menjalankan aplikasi.

Lihat juga