Saya bertanya-tanya, karena banyak hal dapat dilakukan dengan menggunakan refleksi, dapatkah saya mengubah bidang hanya baca pribadi setelah konstruktor menyelesaikan eksekusinya?
(catatan: hanya rasa ingin tahu)
public class Foo
{
private readonly int bar;
public Foo(int num)
{
bar = num;
}
public int GetBar()
{
return bar;
}
}
Foo foo = new Foo(123);
Console.WriteLine(foo.GetBar()); // display 123
// reflection code here...
Console.WriteLine(foo.GetBar()); // display 456
c#
reflection
field
readonly
Ron Klein
sumber
sumber
Hal yang jelas adalah mencobanya:
Ini bekerja dengan baik. (Java memiliki aturan yang berbeda, yang menarik - Anda harus secara eksplisit mengatur
Field
agar dapat diakses, dan itu hanya akan berfungsi untuk bidang contoh.)sumber
Saya setuju dengan jawaban lain yang bekerja secara umum dan terutama dengan komentar oleh E. Lippert bahwa ini bukan perilaku yang terdokumentasi dan karena itu bukan kode bukti masa depan.
Namun, kami juga melihat masalah lain. Jika Anda menjalankan kode Anda di lingkungan dengan izin terbatas Anda mungkin mendapatkan pengecualian.
Kami baru saja mengalami kasus di mana kode kami berfungsi dengan baik di mesin kami, tetapi kami menerima
VerificationException
ketika kode berjalan di lingkungan yang dibatasi. Pelakunya adalah panggilan refleksi ke penyetel bidang hanya baca. Ini berfungsi saat kami menghapus batasan hanya baca di bidang itu.sumber
Anda bertanya mengapa Anda ingin memecahkan enkapsulasi seperti itu.
Saya menggunakan kelas pembantu entitas untuk menghidrasi entitas. Ini menggunakan refleksi untuk mendapatkan semua properti dari entitas kosong baru, dan mencocokkan nama properti / bidang dengan kolom di kumpulan hasil, dan menyetelnya menggunakan propertyinfo.setvalue ().
Saya tidak ingin orang lain dapat mengubah nilainya, tetapi saya juga tidak ingin melakukan semua upaya untuk metode hidrasi kode kustom untuk setiap entitas.
Banyak dari procs saya yang tersimpan mengembalikan hasil yang tidak berhubungan langsung dengan tabel atau tampilan, jadi gen kode ORM tidak melakukan apa-apa untuk saya.
sumber
Cara sederhana lain untuk melakukan ini menggunakan unsafe (atau Anda dapat meneruskan bidang ke metode C melalui DLLImport dan mengaturnya di sana).
sumber
Jawabannya ya, tapi yang lebih penting:
Mengapa Anda ingin? Membobol enkapsulasi secara sengaja sepertinya ide yang sangat buruk bagi saya.
Menggunakan refleksi untuk mengubah bidang baca saja atau konstan seperti menggabungkan Hukum Konsekuensi yang Tidak Diinginkan dengan Hukum Murphy .
sumber
Jangan lakukan ini.
Saya baru saja menghabiskan satu hari untuk memperbaiki bug surealis di mana objek tidak dapat dideklarasikan jenisnya sendiri.
Memodifikasi bidang hanya baca berhasil satu kali. Tetapi jika Anda mencoba memodifikasinya lagi, Anda akan mendapatkan situasi seperti ini:
Jadi jangan lakukan itu.
Ini ada di runtime Mono (mesin game Unity).
sumber
Saya hanya ingin menambahkan bahwa jika Anda perlu melakukan hal ini untuk pengujian unit, maka Anda dapat menggunakan:
A) PrivateObject kelas
B) Anda masih membutuhkan instance PrivateObject, tetapi Anda dapat membuat objek "Accessor" dengan Visual Studio. Cara: Meregenerasi Aksesor Pribadi
Jika Anda menyetel bidang pribadi suatu objek dalam kode Anda di luar pengujian unit, itu akan menjadi contoh "bau kode" Saya pikir mungkin satu-satunya alasan lain Anda ingin melakukan ini adalah jika Anda berurusan dengan pihak ketiga perpustakaan dan Anda tidak dapat mengubah kode kelas target. Meskipun begitu, Anda mungkin ingin menghubungi pihak ketiga, menjelaskan situasi Anda dan melihat apakah mereka tidak mau melanjutkan dan mengubah kode mereka untuk mengakomodasi kebutuhan Anda.
sumber