Beberapa waktu telah berlalu, namun saya belum membaca tanggapan yang memuaskan, jadi saya akan menuliskan apa yang telah saya lakukan di masa lalu. Saya juga masih sangat tertarik dengan pendekatan lain, karena saya merasa apa yang telah saya capai belum ideal dan saya sendiri ingin melakukan yang lebih baik.
Saya telah mencoba, dalam beberapa tahun terakhir, tiga dari empat pendekatan yang terdaftar untuk pembuatan kode kelas "yang diperkaya":
- Refleksi. Memancarkan
- T4
- CodeDom (tapi saya membuang ini lebih awal, karena pada saat proyek saya, belum selesai!)
ditambah tiga lainnya:
- IL menulis ulang menggunakan Profiler API Di Sini dan di sini (sebenarnya digunakan)
- Intersepsi menggunakan ContextBoundObject Di sini (hanya diuji)
- Menyematkan kompiler C# (Roslyn/MonoCSharp) Di sini dan sekarang juga scriptcs (hanya diteliti, tidak benar-benar digunakan)
Secara umum, saya menyelidiki semua alat ini untuk mendapatkan beberapa "jalinan" kode, dengan cara AOP, dimulai dari sesuatu yang mirip dengan contoh OP: membuat kelas dan metode ditandai dengan atribut "khusus", mengubah perilakunya. Pada saat proyek pertama saya, solusi AOP untuk C# belum cukup matang (tapi ini mungkin sudah berubah), jadi saya tidak bisa mengatakan apa pun tentang PostSharp, misalnya. Tujuan saya adalah, seperti yang saya katakan, sangat mirip: berdasarkan atribut pada kelas dan metode, menambahkan beberapa kode tambahan (dan juga anggota kelas) ke kelas. Saya mengakhiri menggunakan Reflection.Emit untuk prototipe, dan IL menulis ulang menggunakan Profiler API untuk hal terakhir.
Proyek kedua, yang akhirnya saya gunakan T4, sedikit berbeda; itu sudah menggunakan pembuat kode (lebih khusus lagi, generator parser), tetapi kami memerlukan modifikasi lebih lanjut (otomatis!) dari kode sumber yang dihasilkan.
Refleksi. Memancarkan
Saya menggunakan pendekatan berikut: sebuah kelas (sebut saja MakeProxy) menjalankan rakitan tertentu, mencari atribut, dan kemudian mengeluarkan dll baru ("proxy") yang disebut rakitan asli, menyediakan antarmuka dan perilaku yang diinginkan kepada pengguna.
Saya sebenarnya menggunakan kelas dalam sebuah alat, .NET yang dapat dieksekusi, yang dijalankan oleh MS Build setelah kompilasi berhasil.
Kerugian utama: referensi mungkin sulit untuk ditangani. Anda perlu mereferensikan dll yang dibuat secara otomatis, jadi Anda harus membagi kode Anda ke dalam proyek yang berbeda, dan Anda bahkan tidak dapat mereferensikan proyek asli dalam suatu solusi... ini mungkin tidak dapat diterima. Selain itu, Anda juga "melihat" (dalam IDE) kode aslinya, dan bukan kode yang dihasilkan; ini mungkin membuat proses debug menjadi sulit.
API Profiler
Dalam hal ini, Anda melakukan pekerjaan yang sama seperti untuk Reflection.Emit, tetapi Anda tidak perlu membuat "proxy" apa pun terlebih dahulu; kode disuntikkan pada waktu pembuatan IL (yaitu sekali, yang merupakan kinerja yang cukup baik). Anda cukup menulis DLL profiler (yang tidak dikelola), dan memulai program Anda di bawahnya. "Profiler" Anda akan diberi tahu tentang fungsi mana yang dijalankan (atau, lebih baik lagi, fungsi mana yang di-JIT) dan Anda dapat bertindak sesuai dengan itu.
Kerugian utama: Anda tidak dapat mengubah "struktur" (metode, bidang,...) kelas Anda (tidak mudah); Pembuatan IL dengan API yang tidak dikelola cukup sulit (Anda harus mengurus banyak hal, dan melakukan debug ketika terjadi kesalahan adalah mimpi buruk yang nyata!) Keuntungan utama: tidak diperlukan modifikasi pada kode asli (terutama, tidak diperlukan modifikasi pada sisi penelepon - inilah yang pada akhirnya mengarahkan saya menuju solusi ini, mengingat persyaratan proyek tertentu).
T4
Saya menggunakan T4 untuk proyek lain, tetapi saya dapat membagikan temuan saya di sini. Ini bagus untuk mengubah teks, tetapi tidak benar-benar untuk mengubah kode: sintaksis menjadi "aneh" (Anda memiliki kode, dan kode di dalam kode untuk menghasilkan kode... Anda mudah tersesat).
Keuntungan utama: terintegrasi dengan baik dengan IDE dan sistem build; Anda mendapatkan dukungan intelijen; mudah untuk memulainya; Anda benar-benar melihat apa yang sedang Anda debug
Secara pribadi, saya ingin memiliki (atau membangun sendiri) sesuatu seperti T4, tetapi itu melakukan transformasi kode C# -> C#; dengan cara itu, Anda bisa mendapatkan keuntungan dari IDE (termasuk intellisense pada barang "asli" dan "produksi") dan kekuatan Reflection.Emit. Anda mungkin perlu membuat kompiler C#/C#, dan plugin VS untuk mendapatkan semua manfaat ini.
Satu catatan terakhir: hari ini, saya akan menggunakan sesuatu yang lebih "canggih" daripada Reflection.Emit, seperti IKVM emit, atau Sigil
person
Lorenzo Dematté
schedule
19.03.2013
Reflection.Emit
? di konstruktorclass
atau di tempat lain? - person Tar   schedule 18.03.2013