Ini adalah bagian terakhir dari seri
Dynamic Language Runtime . Artikel sebelumnya:
- Detail dinamis: game penyamar penyusun, kebocoran memori, nuansa kinerja . Artikel ini membahas cache DLR secara terperinci dan poin-poin yang penting bagi pengembang.
- DLL DLL . Tinjauan umum teknologi, diseksi DynamicMetaObject, dan instruksi singkat tentang cara membuat kelas dinamis Anda sendiri.
Dalam artikel singkat ini, kita akhirnya akan menganalisis kasus-kasus utama penggunaan
dinamis dalam kehidupan nyata: ketika Anda tidak dapat melakukannya tanpa itu dan kapan hal itu dapat sangat memudahkan keberadaan.

Ketika dinamis sangat diperlukan
Tidak ada kasus seperti itu. Anda selalu dapat menulis kode serupa dalam fungsionalitas dalam gaya statis, satu-satunya perbedaan adalah kemudahan membaca dan jumlah kode. Misalnya, saat bekerja dengan objek COM, alih-alih
dinamis, Anda bisa menggunakan refleksi.
Ketika dinamis bermanfaat
Bekerja dengan objek COM
Pertama-tama, ini, tentu saja, bekerja dengan objek COM, yang karenanya semua ini dimulai. Bandingkan kode yang diperoleh dengan
dinamis dan refleksi:
dynamic instance = Activator.CreateInstance(type); instance.Run("Notepad.exe");
var instance = Activator.CreateInstance(type); type.InvokeMember("Run", BindingFlags.InvokeMethod, null, instance, new[] { "Notepad.exe" });
Sebagai aturan, untuk bekerja dengan objek COM melalui refleksi, Anda harus membuat kelas bercabang dengan pembungkus untuk setiap metode / properti. Ada juga barang yang kurang jelas seperti kemampuan untuk tidak mengisi parameter yang tidak Anda butuhkan (wajib dari sudut pandang objek COM) saat memanggil metode melalui
dinamis .
Bekerja dengan konfigurasi
Contoh buku teks lain sedang bekerja dengan konfigurasi, seperti
XML . Tanpa
dinamis :
XElement person = XElement.Parse(xml); Console.WriteLine( $"{person.Descendants("FirstName").FirstOrDefault().Value} {person.Descendants("LastName").FirstOrDefault().Value}" );
Dengan dinamis:
dynamic person = DynamicXml.Parse(xml); Console.WriteLine( $"{person.FirstName} {person.LastName}" );
Tentu saja, untuk ini Anda perlu mengimplementasikan kelas dinamis Anda sendiri. Sebagai alternatif dari daftar pertama, Anda dapat menulis kelas yang akan berfungsi seperti ini:
var person = StaticXml.Parse(xml); Console.WriteLine( $"{person.GetElement("FirstName")} {person.GetElement("LastName")}" );
Tapi, Anda lihat, ini terlihat jauh lebih elegan daripada melalui
dinamis .
Bekerja dengan sumber daya eksternal
Paragraf sebelumnya dapat digeneralisasi untuk tindakan apa pun dengan sumber daya eksternal. Kami selalu memiliki dua alternatif: menggunakan
dinamis untuk mendapatkan kode dalam gaya C # asli atau mengetik statis dengan "garis ajaib". Mari kita lihat contoh dengan permintaan
REST API . Dengan dinamis, Anda dapat menulis ini:
dynamic dynamicRestApiClient = new DynamicRestApiClient("http://localhost:18457/api"); dynamic catsList = dynamicRestApiClient.CatsList;
Di mana kelas dinamis kami akan mengirimkan permintaan formulir atas permintaan properti
[GET] http://localhost:18457/api/catslist
Kemudian dia membatalkan desisialisasi dan mengembalikan kepada kami sejumlah kucing yang sudah siap untuk digunakan. Tanpa
dinamis, akan terlihat seperti ini:
var restApiClient = new RestApiClient("http://localhost:18457/api"); var catsListJson = restApiClient.Get("catsList"); var deserializedCatsList = JsonConvert.DeserializeObject<Cat[]>(catsListJson);
Penggantian Refleksi
Dalam contoh sebelumnya, Anda mungkin memiliki pertanyaan: mengapa dalam satu kasus kami deserializing nilai kembali ke jenis tertentu, dan yang lain tidak? Faktanya adalah bahwa dalam pengetikan statis kita perlu secara eksplisit melemparkan objek ke tipe
Cat untuk bekerja dengannya. Dalam kasus
dinamis , cukup untuk deserialize
JSON menjadi array objek di dalam kelas dinamis kami dan mengembalikan
objek [] dari itu, karena
dinamis mengurus refleksi. Saya akan memberikan dua contoh bagaimana ini bekerja:
dynamic deserialized = JsonConvert.DeserializeObject<object>(serialized); var name = deserialized.Name; var lastName = deserialized.LastName;
Attribute[] attributes = type.GetCustomAttributes(false).OfType<Attribute>(); dynamic attribute = attributes.Single(x => x.GetType().Name == "DescriptionAttribute"); var description = attribute.Description;
Prinsip yang sama seperti ketika bekerja dengan objek COM.
Pengunjung
Dengan menggunakan
dinamis, Anda dapat menerapkan pola ini dengan sangat elegan. Alih-alih seribu kata:
public static void DoSomeWork(Item item) { InternalDoSomeWork((dynamic) item); } private static void InternalDoSomeWork(Item item) { throw new Exception("Couldn't find handler for " + item.GetType()); } private static void InternalDoSomeWork(Sword item) {
Sekarang, ketika melewati objek bertipe
Sword ke metode
DoSomeWork , metode
InternalDoSomeWork (item Sword) akan dipanggil.
Kesimpulan
Kelebihan menggunakan
dinamis :
- Dapat digunakan untuk pembuatan prototipe cepat: dalam banyak kasus, jumlah kode boilerplate berkurang
- Sebagai aturan, ini meningkatkan keterbacaan dan estetika (karena transisi dari "garis ajaib" ke gaya bahasa asli) dari kode
- Meskipun pendapat tersebar luas, berkat mekanisme caching, overhead kinerja yang signifikan dalam kasus umum tidak muncul
Kontra menggunakan dinamis:
- Ada nuansa tidak jelas yang terkait dengan memori dan kinerja.
- Dengan dukungan dan pembacaan kelas dinamis seperti itu, Anda perlu memahami dengan baik apa yang sedang terjadi
- Programmer tidak memiliki pemeriksaan tipe dan semua jaminan kesehatan disediakan oleh kompiler
Kesimpulan
Menurut pendapat saya, pengembang akan menerima keuntungan terbesar dari menggunakan dinamis dalam situasi berikut:
- Saat membuat prototipe
- Dalam proyek kecil / rumah di mana biaya kesalahan rendah
- Dalam utilitas ukuran kode kecil yang tidak menyiratkan waktu jangka panjang. Jika utilitas Anda dieksekusi dalam kasus terburuk selama beberapa detik, biasanya tidak perlu memikirkan kebocoran memori dan penurunan kinerja
Paling tidak kontroversial adalah penggunaan
dinamis dalam proyek kompleks dengan basis kode besar - di sini lebih baik menghabiskan waktu menulis pembungkus statis, sehingga meminimalkan jumlah momen yang tidak jelas.
Jika Anda bekerja dengan objek COM atau domain dalam layanan / produk yang menyiratkan waktu kerja terus menerus yang lama, lebih baik untuk tidak menggunakan
dinamis , meskipun fakta bahwa itu dibuat untuk kasus seperti itu. Bahkan jika Anda benar-benar tahu apa dan bagaimana melakukan dan tidak pernah melakukan kesalahan, cepat atau lambat pengembang baru mungkin datang yang tidak mengetahui hal ini. Hasilnya kemungkinan adalah kebocoran memori yang sulit dihitung.