Runtime: Haruskah ada Reflection.Emit versi .Net Standard 2.0?

Dibuat pada 27 Apr 2018  ·  58Komentar  ·  Sumber: dotnet/runtime

System.Reflection.Emit bukan bagian dari .Net Standard, tetapi ada paket yang memungkinkan Anda menggunakannya dari pustaka .Net Standard (khususnya, System.Reflection.Emit dan System.Reflection.Emit.Lightweight ). Tetapi paket-paket itu tidak memiliki versi .Net Standard 2.0, hanya versi .Net Standard 1.x.

Ini memiliki beberapa implikasi:

  • Pustaka .Net Standard 2.0 tidak dapat menggunakan typeBuilder.CreateType() (meskipun kode ini berfungsi pada .Net Framework 4.6.1 dan .Net Core 2.0) dan harus menggunakan typeBuilder.CreateTypeInfo().AsType() sebagai gantinya. Mungkin juga ada API lain seperti ini.
  • Library .Net Standard 2.0 yang ingin menggunakan Reflection.Emit masih harus menggunakan paket .Net Standard 1.x-style System. *.

Masalah ini akan terpecahkan jika versi .Net Standard 2.0 ditambahkan ke paket Reflection.Emit. Apakah itu sesuatu yang layak dilakukan?

Meskipun keduanya adalah quibbles yang cukup kecil, jadi saya tidak yakin berapa nilai yang akan dilakukan dengan penambahan ini.

area-System.Reflection.Emit question

Komentar yang paling membantu

Terima kasih atas tanggapan semuanya. Berdasarkan masukan yang luar biasa, kami telah mendaftarkan kembali versi terbaru dari paket yang ada:

https://www.nuget.org/packages/System.Reflection.Emit/4.3.0
https://www.nuget.org/packages/System.Reflection.Emit.Lightweight/4.3.0

Namun seperti yang disebutkan sebelumnya di utas ini, paket-paket ini mengklaim kompatibel dengan netstandard1.1 tetapi itu bohong. Mereka hanya akan bekerja pada .NET Core dan .NET Framework. Jadi jika Anda mengonsumsinya dari pustaka netstandard, pustaka itu akan gagal jika dijalankan pada implementasi .NET Standard lainnya.

Kami masih belum memiliki solusi yang bagus untuk mendukung ini di netstandard2.0 tetapi pemilik ( @AtsushiKan @joshfree) System.Relfection.Emit akan mencoba mencari solusi jangka panjang.

Semua 58 komentar

@ericstj @weshaggard apakah Anda tahu apakah ini sengaja dilakukan, atau kekhilafan?

Itu disengaja. Untuk pustaka seperti ini yang memiliki dukungan bergerigi dan tidak ada implementasi portabel, kami menghentikan pengiriman paket. Harapannya adalah Anda menargetkan kerangka kerja tertentu jika Anda membutuhkannya. Untuk beberapa kami telah membawa kembali paket dengan ranjau darat (menerapkan implementasi pada beberapa platform). Orang-orang dapat mengusulkan agar kami menambahkannya kembali tetapi yang satu ini secara khusus telah mengalami perdebatan sengit di masa lalu karena kurangnya dukungan pada semua kerangka kerja .net berbasis AOT. / cc @terrajobst

@tokopedia

Harapannya adalah Anda menargetkan kerangka kerja tertentu jika Anda membutuhkannya.

Bagaimana saya bisa belajar tentang itu? Sejauh yang saya tahu, Reflection.Emit tidak dilaporkan oleh platform-compat. Dan ketika saya google "refleksi memancarkan Net Standar", satu-satunya hasil pada halaman pertama berbicara tentang apakah Anda harus menggunakannya dengan cara adalah tweet dari Juli 2017 oleh @terrajobst menyarankan bahwa Anda harus melakukannya (mungkin situasi berubah sejak saat itu ?).

Saya akan membiarkan @terrajobst menanggapi itu, mungkin dia sedang memikirkan tentang fitur nuget gaurdrails yang kami miliki di paket 1.x dan 1.x. Dengan itu, kami memiliki implementasi yang tidak rata dan dukungan waktu build untuk perpesanan yang tidak didukung. Saya tidak terlalu condong ke satu atau lain cara di sini hanya menjelaskan cara kerja saat ini. Saya pikir jika kita bisa keluar dari orang-orang tentang menambahkan kembali paket dengan platform yang tidak mendukung implementasi, kita bisa melakukannya.

FWIW apa pun yang tersedia dalam kerangka kerja tetapi tidak dalam standar bersih atau dalam pustaka / paket dengan aset standar bersih berarti Anda perlu menargetkan kerangka kerja untuk mendapatkannya. Itu saja yang saya maksud dengan komentar harapan saya.

@tokopedia

apa pun yang tersedia dalam kerangka kerja tetapi tidak dalam standar bersih atau dalam pustaka / paket dengan aset standar bersih berarti Anda perlu menargetkan kerangka kerja untuk mendapatkannya. Itu saja yang saya maksud dengan komentar harapan saya.

Tetapi di sini paket (dengan aset .Net Standard 1.x) memang ada. Saya tidak berpikir Anda bisa berhenti memperbarui paket dan menganggap orang tidak akan menggunakannya lagi. Setidaknya, Anda harus memiliki dokumentasi yang menjelaskan situasinya.

Masalah terbesar dengan System.Reflection.Emit adalah kami tidak memiliki cara untuk menyediakan pustaka dengan cara standar bersih karena TypeInfo (lihat https://github.com/dotnet/corefx/issues/14334). Paket yang ada menargetkan netstandard1.1 tetapi itu bohong dan hanya akan berfungsi pada .NET Framework dan .NET Core karena kopling ketat yang kami miliki. Kami meretasnya untuk bekerja dengan memainkan trik InternalsVisibleTo untuk memberinya akses ke konstruktor TypeInfo, tetapi trik yang sama itulah yang membuatnya tidak berfungsi pada platform standar .NET umum. Kami memutuskan untuk tidak menyebarkan kesalahan lebih lanjut dengan meretas netstandard2.0 dengan cara yang sama dan malah berhenti memproduksi paket dan menjadikannya khusus platform.

Terima kasih telah mengangkat masalah @svick dan kami harus menggunakan masalah ini untuk mendokumentasikan masalah dengan paket.

Bagaimana dengan membatalkan daftar paket yang tidak lagi diperbarui di NuGet sehingga jelas bahwa mereka tidak direkomendasikan?

Itu adalah saran yang masuk akal. Saya baru saja membatalkan semua versi https://www.nuget.org/packages/System.Reflection.Emit/ dan https://www.nuget.org/packages/System.Reflection.Emit.Lightweight

Ini sangat dibutuhkan. Tidak dapat membangun dan menyimpan rakitan saat ini adalah pemblokir terbesar dotnet / corefx # 1 saya untuk memperbarui ke .NET Core, dan saya benar-benar ingin melihat agar kecepatan API yang sangat mendasar ini menjadi prioritas yang lebih tinggi daripada mengerjakan fitur baru .

@masonwheeler hanya untuk memanggil Anda dapat menggunakan Reflection.Emit jika Anda menulis aplikasi atau pustaka .NET Core, Anda tidak dapat menggunakannya saat menulis pustaka .NET Standard saat ini.

@weshaggard apakah kamu yakin? Saya baru saja memeriksa repo, dan tampaknya tidak hanya AssemblyBuilder.Save belum diimplementasikan, itu bahkan tidak ada sama sekali di Core! (Saya mungkin salah; Saya menggunakan ponsel saya dan antarmuka seluler GitHub bukanlah yang terbaik, tetapi seperti itulah tampilannya.)

@masonwheeler Anda benar bahwa kami tidak mendukung AssemblyBuilder. https://github.com/dotnet/corefx/issues/4491.

Itu ada! Saya pikir saya telah melihat masalah itu sebelumnya, tetapi pencarian hanya menemukan yang ini. : P

Tapi ya. Tanpa kemampuan untuk benar - , Anda tidak dapat benar-benar mengatakan bahwa Anda dapat menggunakan Reflection.Emit on Core. ☹️

@weshaggard sebelum paket System.Reflection.Emit.Lightweight tidak terdaftar di nuget.org, dimungkinkan untuk mendapatkan paket Selenium.WebDriver di PowerShell 5 (untuk .Net Framework) dan PowerShell Core 6 (untuk .Net Core 2.0) pada Windows 10 menggunakan perintah berikut: Install-Package Selenium.WebDriver -Destination $ PSScriptRoot -Force -ForceBootstrap

Sekarang perintah ini tidak dapat mengunduh semua dependensi paket Selenium untuk kedua versi PowerShell. Gagal karena paket System.Reflection.Emit.Lightweight.4.3.0 tidak terdaftar di nuget.org.
Kesalahan: Instal-Paket: Tidak dapat menemukan paket yang bergantung (System.Reflection.Emit.Lightweight)

Bisakah Anda memberi saran tentang cara memperbaiki masalah ini?

@SergeyKhutornoy, apakah Anda memanggil "Install-Package" di VS dari Package Manager Console? Jika demikian yang menginstal paket dengan benar untuk saya. Jika Anda memanggil Install-Package dari Powershell, itu adalah jenis manajemen paket yang berbeda. Saya sebenarnya baru mencobanya secara lokal dan saya mendapatkan kesalahan yang berbeda (Instal-Paket: Tidak ada kecocokan yang ditemukan untuk kriteria pencarian yang ditentukan dan nama paket 'Selenium.WebDriver'.) Saya tidak terbiasa dengan sistem manajemen paket itu jadi saya tidak yakin bagaimana cara mengatasinya. Satu hal yang dapat Anda coba adalah menginstal System.Reflection.Emit.Lightweight 4.3.0 secara eksplisit terlebih dahulu dan kemudian melihat apakah berhasil. Jika tidak berhasil, adakah alasan Anda tidak dapat menggunakan VS atau nuget tools untuk menginstal paket?

Tidak mencantumkan paket ini adalah kesalahan, dan tidak memberikan versi .NET Standard 2.0 adalah kesalahan.

Kami akan mengirimkan versi baru utama dari produk kami, NServiceBus, dan kami menargetkan netstandard2.0 . Kami juga memiliki ketergantungan pada System.Reflection.Emit dan System.Reflection.Emit.Lightweight. Saya awalnya bermaksud menargetkan .NET Framework dan .NET Core secara terpisah, tetapi percakapan twitter dengan @terrajobst dikombinasikan dengan menemukan paket-paket ini tersedia membuat saya mengubah paket dan menargetkan netstandard2.0 sebagai gantinya.

Saya tidak keberatan tidak dapat menyimpan rakitan dinamis begitu banyak - saya selalu dapat menguji logika dalam .NET Framework TFM - tetapi DynamicMethod sangat berguna dan sangat banyak digunakan untuk menghasilkan pemikiran refleksi, delegasi konverter dll Paket. System.Reflection.Emit. * Memiliki lebih dari 20.000.000 unduhan.

Harap kembalikan cara untuk mereferensikan DynamicMethod di pustaka netstandard2.0.

Bagaimana kita menggunakan DynamicMethod di .NET Core sekarang setelah tidak terdaftar sebagai sebuah paket?

@danielcrenna Anda tidak memerlukan paket untuk menggunakan DynamicMethod pada .Net Core, karena sudah ada di dalamnya. Anda hanya membutuhkan paket untuk menggunakannya di .Net Standard.

Saya bisa membangun runtime saya (yang sudah dirilis) pada .netstandard 2.0 menggunakan System.Reflection.Emit.Lightweight 4.3 karena saya menggunakan DynamicMethod. Sekarang saya melihat proses build menarik paket dari cache offline dan bukan dari nuget. ~ Jika cache offline disemprot, saya tidak dapat membuat kode lagi untuk .NETstandard. ~ (Menutup cache membuat proses build menarik paket lagi, karena paket masih ada, meskipun tidak terdaftar, jadi ini bukan showstopper secara teknis. Ini secara semantik).

Lihat di sini: https://apisof.net/catalog/System.Reflection.Emit.DynamicMethod apa kesimpulan yang harus saya ambil? Bahwa di NS1.6? Atau di beberapa dimensi antara di mana 'ekstensi platform' valid?

Jadi iow: Saat saya menargetkan .netstandard2.0 dan menggunakan DynamicMethod, saya dapat membuat referensi ke System.Reflection.Emit.Lightweight meskipun tidak terdaftar, dan didukung di ns1.6 (?), Tetapi ini terasa sangat tidak aktif: rasanya seperti kewajiban karena saya sekarang bergantung pada paket yang tidak terdaftar (dan saya kemudian harus berharap paket yang tidak terdaftar disimpan di sana sampai akhir waktu.) Yang menyedihkan adalah: tidak ada alternatif selain bergantung pada paket yang tidak terdaftar yang hanya mungkin karena satu tahu nama persisnya.

// @terraj

Untuk menambahkan: EF Core 2.1 memiliki ketergantungan pada Castle.Core (https://www.nuget.org/packages/Castle.Core/) untuk proxy-nya, yang bergantung pada System.Reflection.Emit.

Bukankah bijaksana bagi semua yang terlibat untuk memiliki paket ini (dan Emit.Lightweight) untuk mendaftar lagi?

@FransBouma secara tegas EF Core Proxies memiliki ketergantungan, bukan EF Core itu sendiri. Tapi bagaimanapun juga itu berantakan.

Sebenarnya _FirebirdClient_ memiliki ketergantungan pada _System.Reflection.Emit_. Dan apa yang harus dilakukan sekarang, bukan?

Meskipun dapat dimengerti bahwa platform AOT penuh tidak dapat mengizinkan jenis baru dibuat saat runtime, lebih mengejutkan bahwa kami tidak dapat mendukung System.Reflection.Emit.Lightweight pada platform ini.
LambdaExpression.Compile() berfungsi di semua platform meskipun ditafsirkan di AOT.

Saya penulis pustaka LightInject DI dan itu menggunakan Reflection.Emit dan DynamicMethod untuk menghasilkan kode saat runtime. Ini semua bagus sampai platform lain ini mulai muncul. SilverLight, WinRT, iOS, dan sebagainya. Lalu apa yang harus dilakukan? Apa yang saya lakukan adalah "shim" DynamicMethod sehingga OpCodes diterjemahkan ke dalam ekspresi. Ada semacam hubungan 1-1 antara Opcode dan ekspresi jadi itu sama sekali tidak sulit.

Lihat implementasinya di sini.
https://github.com/seesharper/LightInject/blob/a01be40607761d9b446dc4acad37d7f717742975/src/LightInject/LightInject.cs#L4483

Perhatikan bahwa saya tidak menerapkan semua Opcode. Hanya yang saya butuhkan.

Maksud saya adalah bahwa mungkin untuk melakukan ini untuk semua OpCodes dan kemudian mengaktifkan BANYAK perpustakaan untuk tetap menargetkan netstandard2.0. Kebanyakan pustaka yang menggunakan Reflection.Emit tidak menghasilkan tipe baru. Mereka hanya menghasilkan kode melalui DynamicMethod

Perhatikan juga bahwa DynamicProxy, Moq, dan pustaka lain yang menghasilkan tipe saat runtime tidak dapat menargetkan netstandard2.0 . Mereka harus netcoreapp karena mereka pada dasarnya mengandalkan AssemblyBuilder dengan teman
Jadi intinya adalah bahwa paket System.Reflection.Emit.Lightweight tidak pernah dapat dihapus seluruhnya dari NuGet sebagai netstandard2.0 . Itu akan menjadi cerita LeftPad lagi

Dua sen saya

Apakah ada daftar di suatu tempat dari TFMs yang mendukung System.Reflection.Emit ? Saya baru saja menambahkan TFM eksplisit net45 dan netcoreapp2.0 ke proyek saya, tetapi saya yakin saya melewatkan beberapa.

@jbogard Semua TFM full framework harusnya bagus selain TFM netcoreapp. Apakah ini di AutoMapper?

Ini sepertinya keputusan yang kurang dipikirkan dan dikomunikasikan dengan konsekuensi yang luas yang tampaknya telah dibuat dengan sedikit keterlibatan dari komunitas yang terkena dampaknya, mengejutkan mengingat paket tersebut memiliki 22 juta unduhan. Bukankah itu menjamin semacam analisis tentang dampak potensial pada setiap orang yang saat ini bergantung padanya?

ServiceStack mereferensikan paket Reflection.Emit yang sekarang dihapus di ServiceStack.Text yang merupakan paket dependensi dasar yang digunakan secara efektif di netstandard2.0 dan net45 build, memaksa penargetan platform .netcore akan memutuskan setiap ketergantungan dan setiap netstandard2.0 proyek yang menggunakannya - yaitu kerangka target yang disukai untuk membuat lintas platform membangun yang mendukung .NET Framework dan .NET Core.

Jadi apa rekomendasi sekarang untuk paket yang menggunakan Reflection.Emit? Hentikan penerbitan build .NET Standard 2.0 dan beri tahu semua orang bahwa mereka tidak lagi dapat membuat build .NET Standard 2.0 untuk pustaka dan proyek mereka?

Solusi sebelumnya untuk menggunakan .NET Standard API yang tidak mengimplementasikan API adalah membuang Pengecualian runtime PlatformNotSupportedException , mengapa sebenarnya itu bukan solusi di sini?

@seesharper ya, saya menambahkan itu tetapi itu mungkin meninggalkan yang lain. Dokumen API mencantumkan lebih banyak tetapi apa lagi yang mungkin hilang dari orang lain? Apakah itu daftar lengkap TFM yang mungkin mendukung API? Bagaimana dengan, katakanlah, xamarinxboxone ?

Saya telah merefaktor kode DynamicMethod / ILGenerator saya yang saya gunakan untuk memancarkan metode penyetel untuk properti saat runtime dengan solusi Lambda.Compile () sehingga ketergantungan pada Reflection.Emit sekarang hilang, namun saya harus menghabiskan 3-4 jam untuk itu yang ingin saya belanjakan untuk hal-hal lain. Tapi sayang, begitulah kehidupan ketika segala sesuatu 'bergerak cepat dan sering pecah', saya kira?

Bagaimanapun, yang menurut saya agak mengganggu adalah keheningan yang memekakkan telinga dari personel Microsoft di utas ini selama beberapa minggu terakhir. Rasanya seperti memperdebatkan hal-hal di sebuah ruangan ketika orang yang sebenarnya bisa mengubah sesuatu tidak ada.

Saya sangat setuju dengan @mythz dan yang lainnya di sini, komunikasi yang buruk, dan dengan 22 juta unduhan, ini adalah keputusan konyol dengan konsekuensi yang luas.

@mythz Saya tidak tahu bagaimana Anda menggunakannya, tetapi untuk barang-barang saya, saya harus kembali ke #if feature flags untuk menghapus fungsionalitas di platform yang tidak mendukung tipe bangunan dengan cepat (di perpustakaan saya, dapat memetakan ke antarmuka dan saya membuat proxy dengan cepat).

@jbogard Kami menggunakan tanda Env.SupportsEmit boolean untuk menentukan pada saat runtime apakah platform mendukung Reflection.Emit, jika memang kami menggunakannya, jika tidak, kami kembali ke Ekspresi Terkompilasi. Pada catatan itu, akan berguna jika ada flag Platform.SupportsEmit yang dapat digunakan semua orang untuk memeriksa apakah platform yang berjalan mendukung Reflection.Emit.

Direktif #if akan membutuhkan pembuatan beberapa build platform yang akan menjadi penyebab perubahan yang merusak untuk semua paket dan proyek dependen yang menargetkan .netstandard2.0 , karena mereka juga memerlukan dependensi .netstandard2.0 .

Hanya untuk diskusi lebih lanjut, saya ingin memastikan bahwa kita semua berada di halaman yang sama dalam hal perbedaan antara System.Reflection.Emit dan System.Reflection.Emit.Lightweight .

Masalah ini seharusnya dipecah menjadi dua masalah terpisah. 😄

  • Haruskah ada Reflection.Emit versi .Net Standard 2.0?
  • Haruskah ada versi .Net Standard 2.0 dari System.Reflection.Emit.LightWeight?

System.Reflection.Emit

Paket ini berisi AssemblyBuilder dan kelas terkait yang kita perlukan untuk menghasilkan rakitan / tipe saat runtime.
Masalah dengan paket ini adalah bahwa ia seharusnya tidak pernah diletakkan di NuGet sebagai paket netstandard karena menghasilkan tipe baru saat runtime tidak dapat didukung pada platform AOT penuh.
Dugaan saya adalah bahwa Microsoft menambahkan ini sebagai paket netstandard untuk mempermudah migrasi dari kerangka penuh ke .Net Core dan perpustakaan netstandard . Kalau dipikir-pikir, sebenarnya bukan ide terbaik.
Pendekatan "umpan dan ganti" (dipahami oleh 5 orang di seluruh dunia) juga bukan solusi yang bagus.

System.Reflection.Emit.LightWeight

Paket ini berisi DynamicMethod yang memungkinkan untuk mengompilasi kode secara dinamis TANPA membuat tipe baru. "Metode dinamis" pada dasarnya adalah metode statis di mana kita dapat membuat delegasi yang digunakan untuk memanggil metode tersebut.
LambdaExpression.Compile pada dasarnya sama dan jika kita melihat implementasi pada kerangka penuh kita akan melihat bahwa itu benar-benar menggunakan DynamicMethod bawah sampulnya.
Masalahnya adalah LambdaExpression.Compile() berfungsi di semua platform menggunakan interpretasi di AOT. Karena itu tidak ada alasan bahwa kita tidak dapat membuat paket System.Reflection.Emit.LightWeight yaitu netstandard menggunakan teknik yang telah saya jelaskan sebelumnya di utas ini.

Dugaan saya adalah bahwa alasan untuk mundur pada ini sekarang adalah untuk memastikan bahwa standar tersebut benar-benar memberi makna di masa depan. Masalahnya seperti yang saya lihat adalah bahwa kita mungkin melihat paket perpustakaan yang menargetkan netcoreapp daripada netstandard dan itu akan sangat buruk ketika harus mengembangkan seluruh konsep netstandard .

Saran saya adalah berusaha mempublikasikan System.Reflection.Emit.LightWeight sebagai paket netstandard yang sebenarnya dan terus mendorong untuk netcoreapp ketika sampai pada System.Reflection.Emit .

@seesharper Sejauh yang saya tahu, Reflection.Emit (termasuk Reflection.Emit.Lightweight) terutama digunakan untuk kinerja. Tetapi jika Anda menerapkan Reflection.Emit.Lightweight menggunakan interpreter IL, kinerjanya kemungkinan besar akan sangat buruk. Jadi saya tidak yakin upaya mendukung mode interpretasi IL di Reflection.Emit.Lightweight akan dibenarkan.

Juga aneh bahwa System.Reflection.Emit.ILGenerator masih terdaftar (https://www.nuget.org/packages/System.Reflection.Emit.ILGeneration), karena ini adalah paket netstandard1.6, namun ILGenerator tidak memiliki implementasi UWP (https://apisof.net/catalog/System.Reflection.Emit.ILGenerator).

Iow: agak berantakan, kan?

@sharen Saran yang bagus.

@svick Saya rasa itu bukan pembenaran yang cukup untuk memotongnya. Bahasa khusus domain memerlukan kemampuan untuk membuat kode pada waktu proses. DSL cukup sering muncul dalam proyek-proyek besar ( aturan kesepuluh Greenspun ), dan lebih baik jika setiap penulis tidak perlu menciptakan dan menulis penerjemah mereka sendiri untuk itu (menggunakan refleksi reguler dan Invoke ). Jika ini adalah komponen standar, setidaknya bagian aturan yang "ditentukan secara informal dan penuh bug" akan dikurangi. Untuk performa implementasi penargetan AOT, tidak harus interpreter IL. Bahkan pada platform yang tidak mengizinkan proses untuk membuat halaman memori yang dapat dieksekusi, seseorang dapat mengkompilasi metode dinamis ke kode berulir seperti yang dilakukan banyak implementasi FORTH, dan untuk metode dinamis kecil di mana "tubuh metode" cocok dengan beberapa baris cache, overhead waktu proses harus cukup rendah.

Masalah dengan paket ini adalah bahwa ia seharusnya tidak pernah diletakkan di NuGet sebagai paket standar bersih karena menghasilkan tipe baru saat runtime tidak dapat didukung pada platform AOT penuh.

Tidak setuju. Platform utama .NET Core dan .NET Framework mendukungnya, hanya karena lingkungan AOT tidak seharusnya menghalangi itu untuk dapat mendukung Platform .NET utama yang menargetkan netstandard2.0 .

Apakah ini sekarang menjadi strategi untuk .NET Standard ke depannya? API yang tidak didukung di lingkungan AOT sekarang akan dihapus? Jadi tidak akan ada lagi PlatformNotSupportedException Pengecualian, API akan ditarik alih-alih bergerak kembali ke subset PCL? Atau apakah kita akan menjadi tidak konsisten dan secara selektif mengurangi permukaan API untuk beberapa fitur tetapi terus membuang yang lain?

Mendukung persimpangan API denominator umum terendah adalah apa yang dilakukan PCL dan menghasilkan pengalaman pengembangan yang mengerikan yang memaksa teknik umpan dan sakelar PCL dan mendelegasikan ke beberapa implementasi khusus platform, yang merupakan semua investasi yang kami buang ketika kami pindah. Standar NET.

Solusi terbaik adalah yang sudah ada (terutama karena menghapusnya sekarang adalah perubahan yang mengganggu dan merusak deps transitifnya) yang memungkinkan kita menggunakan Reflection.Emit di semua platform yang mendukungnya sementara perlu mengimplementasikan fallback untuk mereka yang tidak . Menghapus kemampuan untuk menggunakan Reflection.Emit di .NET Standard berarti pustaka yang menggunakannya tidak dapat lagi menargetkan .NET Standard. Apa gunanya jika kita tidak dapat menggunakan fitur yang dibagikan .NET Core dan .NET Framework dalam abstraksi platform-agnostik? Ini hanya akan menambahkan abstraksi / kebingungan / kompleksitas yang tidak perlu ke ekosistem .NET tanpa manfaat.

Terima kasih atas tanggapan semuanya. Berdasarkan masukan yang luar biasa, kami telah mendaftarkan kembali versi terbaru dari paket yang ada:

https://www.nuget.org/packages/System.Reflection.Emit/4.3.0
https://www.nuget.org/packages/System.Reflection.Emit.Lightweight/4.3.0

Namun seperti yang disebutkan sebelumnya di utas ini, paket-paket ini mengklaim kompatibel dengan netstandard1.1 tetapi itu bohong. Mereka hanya akan bekerja pada .NET Core dan .NET Framework. Jadi jika Anda mengonsumsinya dari pustaka netstandard, pustaka itu akan gagal jika dijalankan pada implementasi .NET Standard lainnya.

Kami masih belum memiliki solusi yang bagus untuk mendukung ini di netstandard2.0 tetapi pemilik ( @AtsushiKan @joshfree) System.Relfection.Emit akan mencoba mencari solusi jangka panjang.

@tokopedia

Sejauh yang saya tahu, Reflection.Emit (termasuk Reflection.Emit.Lightweight) terutama digunakan untuk kinerja. Tetapi jika Anda menerapkan Reflection.Emit.Lightweight menggunakan interpreter IL, kinerjanya kemungkinan besar akan sangat buruk. Jadi saya tidak yakin upaya mendukung mode interpretasi IL di Reflection.Emit.Lightweight akan dibenarkan.

Menurut pemahaman saya bahwa LambaExpression.Compile() dan eksekusinya diinterpretasikan pada platform AOT dan karenanya tidak lebih buruk melakukannya untuk System.Reflection.Emit.LightWeight .
Ada banyak pustaka yang menggunakan paket ini dan memiliki paket netstandard2.0 yang "benar" tiba-tiba akan memungkinkan paket-paket tersebut berjalan di iPhone Anda tanpa memaksa pengembang paket ini untuk menulis ulang kode mereka agar sesuai dengan platform yang berbeda. Performa akan menurun, tetapi akan berfungsi seperti saat ini dengan LambdaExpression.Compile()

@tokopedia

Apakah ini sekarang menjadi strategi untuk .NET Standard ke depannya? API yang tidak didukung di lingkungan AOT sekarang akan dihapus? Jadi tidak akan ada lagi Pengecualian PlatformNotSupportedException, API akan ditarik alih-alih bergerak kembali ke subset PCL? Atau apakah kita akan menjadi tidak konsisten dan secara selektif mengurangi permukaan API untuk beberapa fitur tetapi terus membuang yang lain?

IMHO, melempar PlatformNotSupportedException hanyalah manifestasi lain dari subset API yang kita lihat dengan PCL. Karena kasusnya adalah dengan System.Reflection.Emit.LightWeight , kita benar-benar dapat mengimplementasikannya dan tidak ada alasan untuk melempar PlatformNotSupportedException . Namun saya setuju bahwa itu bermasalah bahwa platform yang kurang mampu membatasi standar untuk bergerak maju. Tapi itu semacam sifat memiliki standar. Ketika penambahan dilakukan pada standar, harus dipastikan bahwa setidaknya mungkin untuk diterapkan oleh platform yang mengimplementasikan standar. Setidaknya di antara pemain utama dan akan mengatakan Xamarin cocok dengan kategori itu.

Sosok yang ada saat ini adalah kebohongan yang saya lihat. Xamarin mengklaim mendukung netstandard , tetapi dukungan itu penuh dengan pengecualian yang bagi kami mungkin tampak masuk akal. Untuk pemula, ini mungkin tidak mudah untuk dimengerti.

image

@tokopedia

Melanjutkan mempublikasikan System.Reflection.Emit sebagai paket netstandard bukanlah solusi yang baik dalam jangka panjang. Itu membuat standar "salah" lagi dan seharusnya hanya tersedia untuk net / netcoreapp. Ini adalah pil pahit untuk ditelan, percayalah, aku tahu. Saya memiliki masalah yang sama persis dengan 'LightInject.Interception' yang merupakan pustaka proxy menggunakan System.Reflection.Emit . Tapi saya lebih suka menargetkan netcoreapp daripada berbohong kepada konsumen bahwa perpustakaan ini dapat berjalan di mana-mana.

@bayu_joo

IMHO, melempar PlatformNotSupportedException hanyalah manifestasi lain dari subset API yang kami lihat dengan PCL. Seperti halnya dengan System.Reflection.Emit.LightWeight, kami benar-benar dapat mengimplementasikannya dan tidak ada alasan untuk menampilkan PlatformNotSupportedException.

Mereka sama sekali tidak setara. Satu-satunya alasan mengapa .NET Standard berguna adalah karena permukaan API-nya yang jauh lebih besar yang memungkinkan kita membuat satu build untuk dijalankan di berbagai platform. PCL jauh kurang berguna karena subset persimpangan API yang dikurangi memaksa pembuatan beberapa build khusus platform untuk fungsionalitas non-sepele. Kemampuan mereka tidak setara dan solusi yang mereka hasilkan sangat berbeda dalam kompleksitas untuk penulis perpustakaan dan konsumen, dengan .NET Standard kami memiliki satu build yang berjalan di semua platform karena kami dapat memeriksa saat runtime jika platform mendukung Reflection.Emit, jika tidak, kita kembali ke Lambda Expressions and Reflection. Jika API ini tidak tersedia untuk pustaka .NET Standard, kami tidak dapat memiliki satu build dan harus kembali ke pengembangan dan pemeliharaan build khusus platform non-portabel.

Melanjutkan menerbitkan System.Reflection.Emit sebagai paket standar bersih bukanlah solusi yang baik dalam jangka panjang. Itu membuat standar "salah" lagi dan seharusnya hanya tersedia untuk net / netcoreapp.

Memaksa pembuatan dan ketergantungan build khusus platform adalah hasil yang jauh lebih buruk, khususnya. dengan begitu banyak dependensi transitif yang sudah bergantung padanya. Manfaat utama .NET Standard adalah dapat membuat perpustakaan dan proyek untuk menargetkan abstraksi tunggal yang berguna, jika kami tidak dapat menggunakannya untuk mengakses fitur utama yang tersedia di .NET Core dan .NET Framework gagal menyelesaikan penggunaan utamanya -case dan mungkin juga tidak ada karena itu hanya menambahkan lebih banyak abstraksi / kebingungan ke ekosistem .NET tanpa manfaat apa pun atas PCL.

PCL sudah mencoba mengikat abstraksi yang hanya mengekspos persimpangan fitur API yang tersedia di setiap platform, yang secara efektif Anda minta untuk kembali, karena Anda hanya akan memiliki akses ke API yang tersedia di setiap platform dan dengan ekstensi hanya berisi API tersedia di platform yang paling terbatas.

Memiliki Permukaan API yang lebih luas di .NET Standard jauh lebih berguna dan memberikan kebebasan kepada penulis perpustakaan untuk dapat memilih bagaimana mereka ingin menangani dukungan untuk platform yang berbeda, jika API ini tidak tersedia maka pilihan itu tidak akan ada, itu akan terjadi. memaksakan pembangunan khusus platform dan memaksa semua pustaka dan proyek yang bergantung untuk juga memelihara pembangunan khusus platform, menambahkan gesekan, fragmentasi, mengurangi portabilitas, dan membatasi dukungan hanya untuk platform yang dipilih penulis untuk mempertahankan versi vs semua platform yang mendukung .NET Standard yang mendukung fitur itu.

Ini bukan hanya masalah preferensi, menghapus dukungan API arus utama memiliki dampak yang sangat mengganggu pada solusi apa yang tersedia, memaksa build khusus platform yang tidak perlu yang berdampak pada utilitas pustaka sambil merusak setiap pustaka dan proyek standar .NET yang menggunakannya.

@tokopedia

Kami masih belum memiliki solusi yang bagus untuk mendukung ini di netstandard2.0 tetapi pemilik ( @AtsushiKan @joshfree) System.Relfection.Emit akan mencoba mencari solusi jangka panjang.

Bagaimana dengan memberi tahu para iDiots dan control freak yang memaksa hanya AOT pada semua orang yang menggunakan platform mereka bahwa mereka perlu membentuk dan memperbaiki aturan platform yang buruk? (Karena jujur ​​saja, kita semua tahu tentang itulah sebenarnya: beberapa aktor jahat yang sangat spesifik di dunia seluler.)

@ Anda memang benar.

@jamur_kejang

Saya benar-benar mengerti bahwa menyembunyikan paket ref emit membuat frustasi, mengingat kerugian yang ditimbulkannya. Saya juga memahami bahwa pengoptimalan kami untuk lingkungan eksekusi yang tidak Anda pedulikan dapat mengganggu, terutama jika ini termasuk trade-off yang memengaruhi skenario yang Anda pedulikan secara negatif.

Karena itu, saya telah menandai komentar Anda sebagai "kasar" karena tidak membangun. Menghina orang tidak akan menyelesaikan masalah ini. Juga pertimbangkan bahwa ini bukan kebijakan yang kami kontrol. Fakta bahwa Anda tidak dapat membuat dan mengeksekusi kode saat runtime di iOS merupakan keputusan kebijakan oleh Apple. Selain itu, dalam beberapa kasus, ini bukan pembatasan kebijakan, tetapi teknologi.

Ada tiga opsi dengan pantulan memancarkan:

  1. Perbaiki paket saat ini dan buat berfungsi di atas .NET Standard 2.0 . Masalahnya adalah hubungan warisan yang aneh antara Type dan TypeInfo di .NET Standard 1.x dibandingkan dengan 2.0 dan memiliki konstruktor non-publik. Saya dapat menjelaskan lebih detail, tetapi untuk membuat paket benar-benar dapat dibangun tanpa mengembalikan ke peretasan agak rumit, itulah sebabnya kami awalnya memutuskan untuk menyembunyikan paket.

  2. Tambahkan pantulan emisi ke .NET Standard vNext . Untuk mendukung skenario AOT saja, ini kemungkinan akan mencakup API kapabilitas yang memungkinkan konsumen untuk memeriksa apakah pembuatan kode didukung atau efisien (yaitu apakah kami menggunakan eksekusi nyata sebagai lawan interpretasi).

  3. Tidak mengekspos refleksi yang dipancarkan ke .NET Standard dan memerlukan penulis perpustakaan untuk multi-target . Ini pada dasarnya adalah jalur asli saat kami mulai menyembunyikan paket.

Saat ini, kami condong ke opsi pertama tetapi opsi kedua juga ada di meja.

Saya mendukung 2. Itu cukup di mana-mana sehingga harus ada di sana. Kami membutuhkan pemeriksaan kemampuan karena alasan lain.

Saya mendukung 2. Itu cukup di mana-mana sehingga harus ada di sana. Kami membutuhkan pemeriksaan kemampuan karena alasan lain.

Saya juga, tetapi itu tidak akan membantu siapa pun yang saat ini mengandalkan .NET Standard 2.0 karena ini memerlukan versi standar yang baru. Namun, API yang dimaksud sudah ada.

Jadi saya berpikir tentang perbaikan minimal untuk membuat paket ini berfungsi sebagaimana adanya tetapi juga memperbaiki .NET Standard 2.0 vNext.

@terrajobst Apakah ada sesuatu tentang opsi 1 yang membuat opsi 2 lebih sulit untuk dilakukan? Bagi saya, mendapatkan versi paket yang menargetkan netstandard2.0 daripada perlu menarik grafik paket netstandard1.1 akan menjadi tujuan jangka pendek yang baik. Kemudian untuk vNext standar, itu bisa menjadi bagian darinya, dan Anda tidak memerlukan paket lagi.

Jadi, kecuali ada alasan bagus untuk tidak melakukannya, saya memilih 1 dan 2.

@bording

Sepertinya kami memposting secara virtual pada waktu yang sama. Semoga komentar saya menjawab pertanyaan Anda :-)

Harap dicatat bahwa netstandard2.0 mendukung System.Reflection.Assembly.Load(byte[] rawAssembly) metode statis, yang memuat rakitan dari array byte gambar biner. Ini berarti bahwa mungkin untuk mengimplementasikan tidak semua kecuali sebagian besar kompatibilitas System.Reflection.Emit API di bawah netstandard2.0 murni.

(Maaf, saya tidak tahu berapa banyak platform yang mendukung Assembly.Load tanpa PNSE)

@GlassGrass kerangka apa yang Anda bayangkan implementasi netstandard2.0 akan diterapkan?

Saya pasti bisa membayangkan beberapa implementasi yang akan menulis IL dan menghasilkan rakitan seperti ILASM yang digerakkan oleh API, tetapi saya tidak melihat kerangka kerja saat ini di mana saya ingin menggunakannya.

Kerangka kerja yang memiliki JIT (dan mendukung Assembly.Load) juga dapat mendukung Ref.Emit secara langsung, dan menyediakan implementasi Ref.Emit mereka alih-alih versi netstandard2.0. Saya tahu ini adalah kasus setidaknya desktop / .netcore / .netnative. Dua yang pertama mendukung ref.emit dan menyediakan implementasi, yang selanjutnya tidak, juga tidak memiliki JIT atau mendukung pemuatan rakitan dinamis.

Saya pikir itu akan menjadi proyek yang menarik bagi seseorang untuk bermain-main di corefxlab untuk menulis sesuatu di atas System.Reflection.Metadata yang terlihat seperti Ref.Emit (atau lebih baik). Tidak yakin apakah ada yang sudah melihatnya. / cc @nguerrera @tv

Saya pikir itu akan menjadi proyek yang menarik bagi seseorang untuk bermain-main di corefxlab untuk menulis sesuatu di atas System.Reflection.Metadata yang terlihat seperti Ref.Emit (atau lebih baik).

Itu ada di piring saya: (https://github.com/dotnet/corefx/issues/4491 dan https://github.com/dotnet/corefx/issues/2800)

https://github.com/dotnet/corefx/issues/2800 akan menjadi yang pertama karena ref emit stuff kemungkinan besar merupakan perpanjangan dari itu. Saya mulai membuat prototipe 2800 minggu ini dan akan melanjutkan pekerjaan itu di bulan-bulan mendatang. Saya tidak akan memindahkannya ke corefxlab sampai saya melangkah lebih jauh. Alur kerja di sana terlalu tidak efisien untuk selera saya.

@AtsushiKan : Senang melihat bahwa masih ada pekerjaan yang sedang berlangsung untuk masalah ini. Terima kasih telah menangani ini.

Saya telah menyebutkan hal berikut di tempat lain sebelumnya: Satu hal yang tidak dapat dilakukan oleh System.Reflection.Metadata dan Assembly.Load(byte[]) adalah pemancar tipe-demi-tipe tambahan. Anda tidak dapat memancarkan satu jenis, lalu jenis lainnya ... Anda hanya dapat memancarkan rakitan lengkap, yang berarti ini tidak terlalu berguna untuk, misalnya, memalsukan pustaka yang mengandalkan generasi jenis proxy dinamis.

Tentu saja seseorang hanya dapat menghasilkan rakitan tipe tunggal, tetapi ini menjadi berpotensi tidak efisien & sulit saat membuat internal terlihat ke rakitan yang dihasilkan secara dinamis melalui [assembly: InternalsVisibleTo] (hal lain yang sering dibutuhkan oleh pustaka pengejek / pengujian). Anda harus dapat memberikan beberapa rakitan tipe tunggal dinamis identitas / nama kuat yang sama agar ini berfungsi. (Runtime mungkin sudah mengizinkan ini dalam praktiknya, tetapi saya tidak dapat menemukan dokumentasi yang secara resmi mengonfirmasi.)

@stakx Anda dapat mengeluarkan System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute ke rakitan dinamis untuk mengizinkannya mengakses anggota non-publik dari rakitan tertentu, daripada menggunakan IVT.

@tmat : Ini menarik. Apakah atribut ini secara resmi didokumentasikan di suatu tempat?

Sangat disayangkan atribut khusus ini tidak didokumentasikan secara resmi, semacam perjudian untuk menggunakannya di luar runtime.

Apakah ini akan ditambahkan ke .NET core 3.0 ?

cc @steveharter @joshfree

@karelz https://github.com/dotnet/corefx/issues/30654 melacak pekerjaan untuk 3.0

@joshfree apakah ini

@ karelz itu menutupi masalah dengan paket Ref.Emit yang salah dihapus dari nuget dan kemudian paket tersebut didaftarkan ulang oleh @weshaggard. Saya pikir masalah ini sekarang dapat ditutup karena pekerjaan yang tersisa dilacak dengan dotnet / corefx # 30654.

OK, tutup kemudian :) ... sisa pekerjaan dilacak di dotnet / corefx # 30654 seperti yang disebutkan di atas.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

EgorBo picture EgorBo  ·  3Komentar

Timovzl picture Timovzl  ·  3Komentar

chunseoklee picture chunseoklee  ·  3Komentar

bencz picture bencz  ·  3Komentar

jchannon picture jchannon  ·  3Komentar