
Malam ini, gelas memulai percakapan tentang bagaimana manajer paket bekerja pada platform yang berbeda. Selama percakapan, kami sampai pada diskusi tentang situasi ketika Anda perlu menghubungkan dua pustaka ke proyek .NET Core yang berisi kelas dengan nama yang sama di namespace yang sama. Karena saya melakukan sedikit. NET Core, saya ingin memeriksa bagaimana masalah ini dapat diselesaikan. Apa yang datang dari ini dijelaskan lebih lanjut
Penafian . Apakah situasi seperti itu sering terjadi? Selama lebih dari 10 tahun bekerja dengan .NET, saya tidak pernah harus menghadapi situasi yang sama dalam proyek nyata. Tetapi percobaan itu menarik.
Untuk berjaga-jaga, saya akan mengklarifikasi bahwa saya akan melakukan percobaan menggunakan:
- macOS 10.13,
- .NET Core SDK 2.1.302
- Penunggang 2018.2
Jadi, kami akan mensimulasikan situasi ketika kami memiliki dua perpustakaan yang memiliki kelas yang kami butuhkan yang harus kami gunakan dalam proyek kami. Pada saat yang sama, kami tidak memiliki akses ke kode sumber, tetapi kami tidak dapat mendekompilasi rakitan untuk mengubah ruang nama di dalamnya, dan kemudian kami juga tidak dapat mengkompilasi kembali.
Persiapan percobaan
Jadi, sebagai permulaan, persiapkan satu burung hantu dan dua bola. Sebagai burung hantu, kami akan memiliki proyek yang menargetkan netcoreapp2.1. Kami akan membuat dua proyek sebagai bola dunia, satu di antaranya juga akan ditargetkan pada netcoreapp2.1, dan yang kedua di netstandard2.0

Di setiap proyek, kami menempatkan kelas Globe, yang akan berada dalam ruang nama yang identik, tetapi mereka akan memiliki implementasi yang berbeda:
File pertama:
using System; namespace Space { public class Globe { public string GetColor() => "Green"; } }
File kedua:
using System; namespace Space { public class Globe { public string GetColor() => "Blue"; } }
Mencoba nomor satu
Karena, sesuai dengan kondisi masalah, kita harus bekerja dengan majelis eksternal, dan bukan proyek, kami akan menambahkan tautan ke proyek sesuai, seolah-olah itu hanya perpustakaan. Untuk melakukan ini, pertama kompilasi semua proyek sehingga kita memiliki Globe1.dll dan Globe2.dll yang kita butuhkan. Kemudian tambahkan tautan ke mereka di proyek sebagai berikut:

Sekarang coba buat variabel kelas Globe:

Seperti yang Anda lihat, sudah pada tahap ini IDE memperingatkan kita bahwa ada masalah dengan pemahaman di mana kelas Globe yang kita butuhkan harus diambil.
Pada awalnya tampaknya situasinya sangat khas dan seharusnya sudah ada, granit siap pakai, jawaban untuk Stack Overflow. Ternyata, belum ada solusi untuk masalah ini yang diusulkan untuk .NET Core. Atau Google saya mengecewakan saya. Tapi saya berhasil menemukan sesuatu yang berguna di Stack Overflow. Satu-satunya publikasi yang masuk akal yang saya kelola untuk google adalah pada tahun 2006 dan menggambarkan situasi yang serupa untuk versi klasik .NET. Dalam hal ini, masalah yang sangat mirip dibahas dalam repositori proyek NuGet .
Sejauh ini, tidak banyak informasi berguna, tetapi masih ada:
Masih memahami bagaimana melakukan ini di .NET Core.
Sayangnya, versi dokumentasi saat ini agak sederhana berbicara tentang kemungkinan menghubungkan paket / biaya eksternal. Dan deskripsi file csproj juga tidak menjelaskan kemungkinan membuat alias. Namun demikian, dengan coba-coba, saya dapat mengetahui bahwa alias untuk rakitan di .NET Core masih didukung. Dan mereka dibuat sebagai berikut:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.1</TargetFramework> </PropertyGroup> <ItemGroup> <Reference Include="Globe1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> <HintPath>..\Globe1\bin\Debug\netcoreapp2.1\Globe1.dll</HintPath> <Aliases>Lib1</Aliases> </Reference> <Reference Include="Globe2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> <HintPath>..\Globe2\bin\Debug\netstandard2.0\Globe2.dll</HintPath> <Aliases>Lib2</Aliases> </Reference> </ItemGroup> </Project>
Sekarang tinggal belajar bagaimana menggunakan alias ini. Kata kunci eksternal yang disebutkan sebelumnya akan membantu kami dalam hal ini:
Berikut ini ditulis dalam dokumentasi tentang hal itu:
Dalam beberapa kasus, Anda mungkin perlu merujuk dua versi rakitan dengan nama jenis yang sepenuhnya memenuhi syarat. Misalnya, Anda perlu menggunakan dua atau lebih versi perakitan dalam satu aplikasi. Menggunakan alias rakitan eksternal, Anda dapat menyertakan ruang nama untuk setiap rakitan dalam pembungkus di dalam ruang nama tingkat root yang dinamai oleh alias ini, yang memungkinkan Anda untuk menggunakannya dalam satu file.
...
Setiap deklarasi alias eksternal memperkenalkan ruang nama level root tambahan yang cocok dengan namespace global (tetapi tidak ada di dalamnya). Dengan demikian, referensi ke tipe dari setiap perakitan tanpa ambiguitas dapat dibuat menggunakan nama lengkapnya, yang root adalah alias namespace yang sesuai.
Yang benar di sini adalah jangan lupa bahwa extern juga digunakan dalam C # untuk mendeklarasikan metode dengan implementasi eksternal dari kode yang tidak dikelola. Dalam hal ini, extern biasanya digunakan dengan atribut DllImport. Anda dapat membaca lebih lanjut tentang ini di bagian yang sesuai dari dokumentasi .
Jadi, mari kita coba gunakan alias kita:
extern alias Lib1; extern alias Lib2; using System; namespace Owl { ... public class SuperOwl { private Lib1::Space.Globe _firstGlobe; private Lib2::Space.Globe _secondGlobe; public void IntegrateGlobe(Lib1::Space.Globe globe) => _firstGlobe = globe; public void IntegrateGlobe(Lib2::Space.Globe globe) => _secondGlobe = globe; ... } }
Kode ini bahkan sudah berfungsi. Dan itu bekerja dengan benar. Tapi saya tetap ingin membuatnya sedikit lebih elegan. Ini dapat dilakukan dengan cara yang sangat sederhana:
extern alias Lib1; extern alias Lib2; using System; using SpaceOne=Lib1::Space; using SpaceTwo=Lib2::Space;
Sekarang Anda dapat menggunakan sintaks yang biasa dan jelas:
var globe1 = new SpaceOne.Globe() var globe2 = new SpaceTwo.Globe()
Tes
Mari kita uji burung hantu kita:

Seperti yang Anda lihat, kode berfungsi dengan baik dan tanpa kesalahan. Integrasi burung hantu dan bola telah berhasil diselesaikan!
→ Kode sampel tersedia di GitHub