Saya ingin mengakses nilai dynamic
properti c # dengan string:
dynamic d = new { value1 = "some", value2 = "random", value3 = "value" };
Bagaimana saya bisa mendapatkan nilai d.value2 ("acak") jika saya hanya memiliki "value2" sebagai string? Dalam javascript, saya bisa melakukan d ["value2"] untuk mengakses nilai ("acak"), tapi saya tidak yakin bagaimana melakukan ini dengan c # dan refleksi. Yang paling dekat saya datang adalah ini:
d.GetType().GetProperty("value2")
... tapi saya tidak tahu bagaimana mendapatkan nilai aktual dari itu.
Seperti biasa, terima kasih atas bantuan Anda!
Jawaban:
Setelah Anda memiliki
PropertyInfo
(dariGetProperty
), Anda perlu meneleponGetValue
dan mengirimkan contoh yang Anda ingin dapatkan nilainya. Dalam kasus Anda:sumber
'd.GetType().GetProperty("value2").GetValue(d)' threw an exception of type 'System.Reflection.TargetInvocationException' dynamic {System.Reflection.TargetInvocationException}
di jendela arloji dengan itu ..?new {}
membuat tipe anonim nyata dengan properti yang ditentukan, memanggil GetType / GetProperty masuk akal, tetapi bagaimana dengan ExpandoObject, yang jika Anda panggil GetType, Anda akan mendapatkan tipe yang memiliki properti ExpandoObject, tetapi belum tentu sifat dinamisnya.Tambahkan referensi ke Microsoft.CSharp. Bekerja juga untuk tipe dinamis dan properti dan bidang pribadi.
Sunting : Sementara pendekatan ini berhasil, ada hampir 20 × metode lebih cepat dari perakitan Microsoft.VisualBasic.dll :
sumber
d
dalam pertanyaan).CallSite
kode vsCallByName
kode apakah Anda membandingkan keduanya saat melakukan cachingCallSite
instance? Saya akan curiga biaya metode pertama Anda hampir murni aktivasiBinder
danCallSite
, bukan doaTarget()
Dynamitey adalah
.net std
pustaka sumber terbuka , yang memungkinkan Anda menyebutnya sepertidynamic
kata kunci, tetapi menggunakan string untuk nama properti daripada kompiler yang melakukannya untuk Anda, dan akhirnya sama dengan refleksi dengan cepat (yang hampir tidak secepat cepat) seperti menggunakan kata kunci dinamis, tetapi ini disebabkan oleh overhead tambahan caching secara dinamis, di mana kompiler melakukan cache secara statis).sumber
Metode termudah untuk mendapatkan a
setter
dan agetter
untuk properti yang bekerja untuk semua jenis termasukdynamic
danExpandoObject
menggunakanFastMember
yang juga merupakan metode tercepat di sekitar (menggunakan Emit).Anda bisa mendapatkan
TypeAccessor
berdasarkan pada jenis tertentu atauObjectAccessor
berdasarkan contoh dari jenis tertentu.Contoh:
sumber
Sebagian besar waktu ketika Anda meminta objek dinamis, Anda mendapatkan ExpandoObject (tidak dalam contoh yang diketik secara anonim-tapi-statis di atas, tetapi Anda menyebutkan JavaScript dan parser JSON pilihan saya JsonFx, misalnya, menghasilkan ExpandoObjects).
Jika dinamika Anda sebenarnya adalah ExpandoObject, Anda dapat menghindari refleksi dengan mengirimkannya ke IDictionary, seperti yang dijelaskan di http://msdn.microsoft.com/en-gb/library/system.dynamic.expandoobject.aspx .
Setelah Anda menggunakan IDictionary, Anda memiliki akses ke metode yang berguna seperti .Item dan .ContainsKey
sumber
Int64? i = data.value; //data is ExpandoObject
secara otomatis akan mencari dan memanggil operator implisit. Di sisi lain, jika saya harus menggunakan IDictionary untuk menguji apakah bidang "nilai" ada, saya akan mendapatkan objek kembali yang tidak akan dilemparkan tanpa kesalahan ke Int64 ?.GetProperty / GetValue tidak berfungsi untuk data Json, itu selalu menghasilkan pengecualian nol, namun, Anda dapat mencoba pendekatan ini:
Serialize objek Anda menggunakan JsonConvert:
Kemudian mengaksesnya langsung melemparkannya kembali ke string:
Mungkin bekerja langsung menerapkan Convert.ToString (permintaan) ["DynamicFieldName"], namun saya belum menguji.
sumber
new JavaScriptSerializer().Deserialize<object>(json);
untuk sampai ke "properti" dengan cara yang Anda sarankanmengembalikan objek PropertyInfo.
Jadi lakukan
sumber
GetValue(d)
perluGetValue(d,null)
Ini adalah cara saya mendapatkan nilai dari nilai properti dinamis:
sumber
Untuk mendapatkan properti dari dokumen dinamis saat
.GetType()
kembalinull
, coba ini:sumber
Di .Net inti 3.1 Anda dapat mencoba seperti ini
sumber
Mirip dengan jawaban yang diterima, Anda juga dapat mencoba
GetField
bukanGetProperty
.d.GetType().GetField("value2").GetValue(d);
Bergantung pada bagaimana sebenarnya
Type
diterapkan, ini dapat bekerja ketika GetProperty () tidak dan bahkan bisa lebih cepat.sumber