Jawaban:
Kata dynamickunci tersebut digunakan untuk mendeklarasikan variabel yang harus diikat.
Jika Anda ingin menggunakan pengikatan yang lebih lambat, untuk semua tipe nyata atau yang dibayangkan, Anda menggunakan dynamickata kunci dan sisanya adalah kompiler.
Saat Anda menggunakan dynamickata kunci untuk berinteraksi dengan mesin virtual normal, DLR melakukan panggilan yang terlambat ke metode normal mesin virtual tersebut.
The IDynamicMetaObjectProviderantarmuka memungkinkan kelas untuk mengambil kendali dari perilaku akhir-terikat nya.
Ketika Anda menggunakan dynamickata kunci untuk berinteraksi dengan IDynamicMetaObjectProviderimplementasi, DLR memanggil IDynamicMetaObjectProvidermetode dan objek itu sendiri memutuskan apa yang harus dilakukan.
The ExpandoObjectdan DynamicObjectkelas implementasi dari IDynamicMetaObjectProvider.
ExpandoObjectadalah kelas sederhana yang memungkinkan Anda untuk menambahkan anggota ke instance dan menggunakannya sebagai dynamicsekutu.
DynamicObjectadalah implementasi yang lebih maju yang dapat diwarisi untuk dengan mudah memberikan perilaku yang disesuaikan.
Saya akan mencoba memberikan jawaban yang lebih jelas untuk pertanyaan ini, untuk menjelaskan dengan jelas apa perbedaan antara dinamis, ExpandoObjectdan DynamicObject.
Sangat cepat, dynamicadalah kata kunci. Ini bukan tipe per-se. Ini adalah kata kunci yang memberitahu kompiler untuk mengabaikan pengecekan tipe statis pada waktu desain dan alih-alih menggunakan pengikatan yang terlambat pada waktu berjalan. Jadi kita tidak akan menghabiskan banyak waktu dynamicdi sisa jawaban ini.
ExpandoObjectdan DynamicObjectmemang tipe. Di PERMUKAAN, mereka terlihat sangat mirip satu sama lain. Kedua kelas menerapkan IDynamicMetaObjectProvider. Namun, gali lebih dalam dan Anda akan menemukan bahwa mereka TIDAK serupa.
DynamicObject adalah implementasi parsial yang IDynamicMetaObjectProvidermurni dimaksudkan sebagai titik awal bagi pengembang untuk mengimplementasikan tipe kustom mereka sendiri yang mendukung pengiriman dinamis dengan penyimpanan yang mendasari kustom dan perilaku pengambilan untuk membuat pengiriman dinamis berfungsi.
Singkatnya, gunakan DynamicObject ketika Anda ingin membuat tipe SENDIRI yang dapat digunakan dengan DLR dan bekerja dengan perilaku CUSTOM apa pun yang Anda inginkan.
Contoh: Bayangkan bahwa Anda ingin memiliki tipe dinamis yang mengembalikan default khusus setiap kali mencoba anggota yang TIDAK ada (yaitu belum ditambahkan pada waktu berjalan). Dan default itu akan berkata, "Maaf, tidak ada cookie di toples ini!". Jika Anda menginginkan objek dinamis yang berperilaku seperti ini, Anda harus mengontrol apa yang terjadi ketika bidang tidak ditemukan. ExpandoObject tidak akan membiarkan Anda melakukan ini. Jadi, Anda harus membuat tipe Anda sendiri dengan perilaku resolusi (pengiriman) anggota dinamis yang unik dan menggunakannya daripada yang sudah jadi ExpandoObject.
Anda dapat membuat jenis sebagai berikut: (Catatan, kode di bawah ini hanya untuk ilustrasi dan mungkin tidak berjalan. Untuk mempelajari tentang cara menggunakan DynamicObject dengan benar, ada banyak artikel dan tutorial di tempat lain.)
public class MyNoCookiesInTheJarDynamicObject : DynamicObject
{
Dictionary<string, object> properties = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (properties.ContainsKey(binder.Name))
{
result = properties[binder.Name];
return true;
}
else
{
result = "I'm sorry, there are no cookies in this jar!"; //<-- THIS IS OUR
CUSTOM "NO COOKIES IN THE JAR" RESPONSE FROM OUR DYNAMIC TYPE WHEN AN UNKNOWN FIELD IS ACCESSED
return false;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
properties[binder.Name] = value;
return true;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
dynamic method = properties[binder.Name];
result = method(args[0].ToString(), args[1].ToString());
return true;
}
}
Sekarang, kita bisa menggunakan kelas imajiner yang baru saja kita buat sebagai tipe dinamis yang memiliki perilaku sangat khusus jika bidang tidak ada.
dynamic d = new MyNoCookiesInTheJarDynamicObject();
var s = d.FieldThatDoesntExist;
//in our contrived example, the below should evaluate to true
Assert.IsTrue(s == "I'm sorry, there are no cookies in this jar!")
ExpandoObjectadalah implementasi LENGKAP dari IDynamicMetaObjectProvider, di mana tim .NET Framework telah membuat semua keputusan ini untuk Anda. Ini berguna jika Anda tidak memerlukan perilaku khusus, dan Anda merasa bahwa ExpandoObject bekerja cukup baik untuk Anda (90% dari waktu, ExpandoObjectcukup baik). Jadi misalnya, lihat yang berikut ini, dan untuk ExpandoObject, desainer memilih untuk melemparkan pengecualian jika anggota dinamis tidak ada.
dynamic d = new ExpandoObject();
/*
The ExpandoObject designers chose that this operation should result in an
Exception. They did not have to make that choice, null could
have been returned, for example; or the designers could've returned a "sorry no cookies in the jar" response like in our custom class. However, if you choose to use
ExpandoObject, you have chosen to go with their particular implementation
of DynamicObject behavior.
*/
try {
var s = d.FieldThatDoesntExist;
}
catch(RuntimeBinderException) { ... }
Jadi untuk meringkas, ExpandoObjecthanyalah satu cara yang dipilih sebelumnya untuk memperluas DynamicObject dengan perilaku pengiriman dinamis tertentu yang mungkin akan bekerja untuk Anda , tetapi mungkin tidak tergantung pada kebutuhan khusus Anda.
Sedangkan, DyanmicObjectadalah tipe dasar pembantu yang membuat menerapkan tipe Anda sendiri dengan perilaku dinamis yang unik sederhana dan mudah.
Tutorial bermanfaat yang menjadi dasar dari banyak contoh sumber di atas.
DynamicObject: ketika menimpa TryGetMember, jika Anda mengembalikan false, RuntimeBinderExceptionakan dilemparkan ketika mencoba mengakses ke properti yang tidak ada. Agar snipet benar-benar berfungsi, Anda harus kembali true.
Menurut spesifikasi bahasa C # dynamicadalah deklarasi jenis. Yaitu dynamic xberarti variabel xmemiliki tipedynamic .
DynamicObject adalah tipe yang membuatnya mudah diimplementasikan IDynamicMetaObjectProvider dan dengan demikian mengesampingkan perilaku mengikat spesifik untuk tipe tersebut.
ExpandoObjectadalah jenis yang bertindak seperti tas properti. Yaitu Anda dapat menambahkan properti, metode, dan sebagainya ke contoh dinamis dari tipe ini saat runtime.
dynamicbukan tipe aktual ... itu hanya sebuah petunjuk untuk memberitahu kompiler untuk menggunakan pengikatan akhir untuk variabel ini. dynamicvariabel sebenarnya dideklarasikan seperti objectdalam MSIL
Contoh di atas DynamicObjecttidak memberi tahu perbedaannya, karena pada dasarnya menerapkan fungsi yang sudah disediakan olehExpandoObject .
Dalam dua tautan yang disebutkan di bawah ini, sangat jelas bahwa dengan bantuan DynamicObject , dimungkinkan untuk melestarikan / mengubah tipe aktual ( XElementdalam contoh yang digunakan dalam tautan di bawah) dan kontrol yang lebih baik pada properti dan metode.
public class DynamicXMLNode : DynamicObject
{
XElement node;
public DynamicXMLNode(XElement node)
{
this.node = node;
}
public DynamicXMLNode()
{
}
public DynamicXMLNode(String name)
{
node = new XElement(name);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
XElement setNode = node.Element(binder.Name);
if (setNode != null)
setNode.SetValue(value);
else
{
if (value.GetType() == typeof(DynamicXMLNode))
node.Add(new XElement(binder.Name));
else
node.Add(new XElement(binder.Name, value));
}
return true;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
XElement getNode = node.Element(binder.Name);
if (getNode != null)
{
result = new DynamicXMLNode(getNode);
return true;
}
else
{
result = null;
return false;
}
}
}