Saat bermigrasi dari
.NET Framework ke
.NET Core , beberapa momen tidak menyenangkan mungkin muncul. Misalnya, jika aplikasi Anda menggunakan domain, Anda harus menulis ulang logikanya. Situasi yang serupa dengan
Thread.Abort () :
Microsoft sangat
tidak disukai oleh praktik ini (dan memang demikian) bahwa mereka pertama kali menyatakan metode ini
sudah usang , dan kemudian benar-benar memotongnya keluar dari kerangka kerja dan sekarang dengan berbahaya melempar
PlatformNotSupportedException .
Tetapi bagaimana jika aplikasi Anda menggunakan
Thread.Abort () , dan Anda
benar -
benar ingin menerjemahkannya ke
.NET Core tanpa menulis ulang apa pun? Yah, kami tahu betul bahwa platform bahkan mendukung fungsi ini, jadi saya bisa menyenangkan Anda: ada jalan keluar, Anda hanya perlu merakit versi
CLR Anda sendiri.
Penafian: Ini adalah artikel yang sepenuhnya praktis dengan teori minimum, yang dirancang hanya untuk menunjukkan pilihan baru untuk interaksi antara pengembang dan lingkungan .NET. Jangan pernah melakukan ini dalam produksi. Tetapi jika Anda benar-benar ingin ...
Ini dimungkinkan berkat dua hal: keinginan
Microsoft untuk cross-platform
.NET Core dan pekerjaan yang dilakukan oleh pengembang untuk mentransfer kode sumber kerangka kerja untuk membuka akses. Mari manfaatkan ini.
Minimum teoritis:
- mempublikasikan dotnet memungkinkan kita untuk mempublikasikan aplikasi mandiri : kerangka kerja akan dikirimkan bersamanya, dan tidak mencari di suatu tempat di GAC
- Versi CoreCLR di mana aplikasi akan berjalan, dalam kondisi tertentu, dapat diatur menggunakan runtimeconfig.json
- Kita dapat membangun CoreFX kita sendiri: github.com/dotnet/corefx
- Kita dapat membangun CoreCLR kita sendiri: github.com/dotnet/coreclr
Kustomisasi CoreFX
Sebelum beralih ke tujuan utama kami - mengembalikan
Thread.Abort ( ) - mari kita ubah sesuatu yang mendasar di
CoreFX untuk
pemanasan untuk menguji fungsionalitas semua alat. Sebagai contoh, dalam jejak artikel saya
sebelumnya tentang
dinamis , kami sepenuhnya melarang penggunaannya dalam aplikasi. Mengapa Karena kita bisa.
Prasyarat
Pertama-tama, kami akan menginstal
semua yang diperlukan untuk perakitan:
- CMake
- Visual Studio 2019 Pratinjau
- .NET Core SDK terbaru (.NET Core 3.0 Preview)
Visual Studio 2019 - Beban Kerja
Pengembangan desktop .NET- Semua Komponen yang Diperlukan
- .NET Framework 4.7.2 Alat Pengembangan
Pengembangan desktop dengan C ++- Semua Komponen yang Diperlukan
- Toolset VC ++ 2019 v142 (x86, x64)
- Windows 8.1 SDK dan UCRT SDK
- Toolset VC ++ 2017 v141 (x86, x64)
.NET Core pengembangan lintas platform- Semua Komponen yang Diperlukan
Visual Studio 2019 - Komponen individual
- C # dan Visual Basic Roslyn Compiler
- Alat Analisis Statis
- .NET Portable Library Targeting Pack
- Windows 10 SDK atau Windows 8.1 SDK
- Visual Studio C ++ Fitur Inti
- Toolset VC ++ 2019 v142 (x86, x64)
- Toolset VC ++ 2017 v141 (x86, x64)
- Msbuild
- .NET Framework 4.7.2 Paket Penargetan
- Windows Universal CRT SDK
Klon corefx :
git clone https://github.com/dotnet/corefx.git
Sekarang nonaktifkan
dinamis . Kami akan terbuka untuk ini (selanjutnya saya akan menunjukkan jalur relatif ke akar repositori)
corefx\src\System.Linq.Expressions\src\System\Runtime\CompilerServices\CallSite.cs
Dan di akhir fungsi
CallSite <T>
.Create, masukkan kode biasa:
throw new PlatformNotSupportedException("No way");
Kami kembali ke
corefx dan menjalankan
build.cmd . Setelah perakitan selesai, buat proyek
.NET Core baru di
Visual Studio dengan konten berikut:
public int Test { get; set; } public static void Main(string[] args) { try { dynamic a = new Program(); a.Test = 120; } catch (Exception e) { Console.WriteLine(e); }
Kami menyusun proyek kami. Sekarang pergilah ke
corefx\artifacts\packages\Debug\NonShipping
dan kami menemukan ada paket yang terlihat seperti ini:
Microsoft.Private.CoreFx.NETCoreApp. 5.0.0-dev.19465.1 .nupkg . Kami membuka
.csproj proyek kami dan menyisipkan baris berikut di sana:
<PropertyGroup> <PackageConflictPreferredPackages>Microsoft.Private.CoreFx.NETCoreApp;runtime.$(RuntimeIdentifiers).Microsoft.Private.CoreFx.NETCoreApp;$(PackageConflictPreferredPackages)</PackageConflictPreferredPackages> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Private.CoreFx.NETCoreApp" Version="5.0.0-dev.19465.1" /> </ItemGroup>
Versi harus sama dengan nama paket yang dirakit. Dalam kasus saya,
5.0.0-dev.19465.1 .

Buka pengaturan
nuget untuk proyek kami dan tambahkan dua jalur baru di sana:
corefx\artifacts\packages\Debug\NonShipping corefx\artifacts\packages\Debug\Shipping
Dan hapus centang semua yang lain.

Buka folder proyek dan jalankan
dotnet publish --runtime win-x64 --self-contained
Selesai! Tetap berjalan:

Itu berhasil! Perpustakaan tidak diambil dari
GAC ,
dinamis tidak berfungsi.
Buat CoreCLR Hebat Lagi
Sekarang mari kita beralih ke bagian kedua, mengembalikan
Thread.Abort () . Kejutan yang tidak menyenangkan menunggu kita di sini: Implementasi
utas terletak pada
CoreCLR , yang bukan bagian dari
CoreFX dan sudah diinstal sebelumnya pada mesin secara terpisah. Pertama, buat proyek demo:
var runtimeInformation = RuntimeInformation.FrameworkDescription; Console.WriteLine(runtimeInformation); var thr = new Thread(() => { try { while (true) { Console.WriteLine("."); Thread.Sleep(500); } } catch (ThreadAbortException) { Console.WriteLine("Thread aborted!"); } }); foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { Console.WriteLine(asm.Location); } thr.Start(); Thread.Sleep(2000); thr.Abort();
Mengempiskan coreclr . Temukan file
coreclr\src\System.Private.CoreLib\shared\System\Threading\Thread.cs
Dan ganti
Abort () dengan
[SecuritySafeCritical] [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] public void Abort() { AbortInternal(); } [System.Security.SecurityCritical]
Sekarang kita perlu mengembalikan atribut dan implementasi
c ++ . Saya mengumpulkannya dalam beberapa bagian dari berbagai repositori terbuka
.NET Framework dan untuk kenyamanan saya merancang semua perubahan dalam bentuk
permintaan tarik .
Catatan: saat membangun, ada masalah dengan sumber daya di atribut "baru", yang saya
"Tetap" dengan colokan. Ingatlah hal ini jika Anda ingin menggunakan kode ini di mana pun selain eksperimen di rumah.Setelah mengintegrasikan perubahan ini ke dalam kode, jalankan
build.cmd dari
coreclr . Perakitan pada tahap selanjutnya mungkin mulai menaburkan kesalahan, tapi itu tidak menakutkan, hal utama bagi kami adalah bahwa
CoreCLR dapat berkumpul. Itu akan terletak di:
coreclr\bin\Product\Windows_NT.x64.Debug
Cara mudah
Kami melakukan
dotnet publish --runtime win-x64 --self-contained
File dari
Windows_NT.x64.Debug dijatuhkan ke folder dengan aplikasi yang diterbitkan.
Cara yang sulit
Setelah perpustakaan dirakit, buka
C:\Program Files\dotnet\shared\Microsoft.NETCore.App
dan mengkloning folder 3.0.0. Kami akan menyebutnya, misalnya, 5.0.1. Kami menyalin semua yang ada di
Windows_NT.x64.Debug , kecuali foldernya. Sekarang versi
CoreCLR kami akan tersedia melalui runtimeconfig.
Menyatukan proyek kami. Tambahkan ke
.csproj :
<PropertyGroup> <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences> <PackageConflictPreferredPackages>Microsoft.Private.CoreFx.NETCoreApp;runtime.$(RuntimeIdentifiers).Microsoft.Private.CoreFx.NETCoreApp;$(PackageConflictPreferredPackages)</PackageConflictPreferredPackages> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Private.CoreFx.NETCoreApp" Version="5.0.0-dev.19465.1" /> </ItemGroup>
Kami mengulangi manipulasi dengan
nuget dari bagian artikel sebelumnya. Terbitkan
dotnet publish --runtime win-x64 --self-contained
Di
runtimeconfig.json, masukkan konfigurasi berikut:
{ "runtimeOptions": { "tfm": "netcoreapp3.0", "framework": { "name": "Microsoft.NETCore.App", "version": "5.0.1" } } }
Hasil
Luncurkan!

Keajaiban itu terjadi. Sekarang di aplikasi
.NET Core kami
Thread.Abort () berjalan kembali. Tapi, tentu saja, hanya di
Windows .