Terminologi dari pertanyaan tidak benar-benar cocok dengan kode contoh. Ini Ambient Context
adalah pola yang digunakan untuk mengambil ketergantungan dari kelas mana saja di modul apa pun semudah mungkin, tanpa mencemari setiap kelas untuk menerima antarmuka ketergantungan, tetapi tetap mempertahankan gagasan inversi kontrol. Ketergantungan seperti itu biasanya didedikasikan untuk logging, keamanan, manajemen sesi, transaksi, caching, audit sehingga untuk masalah lintas sektoral dalam aplikasi itu. Ini entah bagaimana menjengkelkan untuk menambahkan ILogging
, ISecurity
, ITimeProvider
untuk konstruktor dan sebagian besar waktu tidak semua kelas perlu semua pada saat yang sama, jadi saya mengerti kebutuhan Anda.
Bagaimana jika masa pakai ISession
instance berbeda dengan yang ILogger
ada? Mungkin instance ISession harus dibuat pada setiap permintaan dan ILogger sekali. Jadi memiliki semua dependensi ini diatur oleh satu objek yang bukan wadah itu sendiri tidak terlihat pilihan yang tepat karena semua masalah ini dengan manajemen seumur hidup dan lokalisasi dan lainnya yang dijelaskan dalam utas ini.
Pertanyaan IAmbientContext
di atas tidak menyelesaikan masalah tidak mencemari setiap konstruktor. Anda masih harus menggunakannya dalam tanda tangan konstruktor, tentu saja, hanya sekali saja kali ini.
Jadi cara termudah BUKAN menggunakan injeksi konstruktor atau mekanisme injeksi lainnya untuk menangani dependensi lintas bidang, tetapi menggunakan panggilan statis . Kami sebenarnya melihat pola ini cukup sering, diimplementasikan oleh kerangka itu sendiri. Periksa Thread.CurrentPrincipal yang merupakan properti statis yang mengembalikan implementasi IPrincipal
antarmuka. Ini juga dapat diatur sehingga Anda dapat mengubah implementasinya jika Anda suka, sehingga Anda tidak dapat menggunakannya.
MyCore
terlihat seperti sekarang
public class MyCoreClass
{
public void BusinessFeature(string data)
{
LoggerContext.Current.Log(data);
_repository.SaveProcessedData();
SessionContext.Current.SetData(data);
...etc
}
}
Pola ini dan kemungkinan implementasi telah dijelaskan secara rinci oleh Mark Seemann dalam artikel ini . Mungkin ada implementasi yang bergantung pada wadah IoC sendiri yang Anda gunakan.
Anda ingin menghindari AmbientContext.Current.Logger
, AmbientContext.Current.Session
untuk alasan yang sama seperti yang dijelaskan di atas.
Tetapi Anda memiliki opsi lain untuk menyelesaikan masalah ini: gunakan dekorator, intersepsi dinamis jika wadah Anda memiliki kemampuan ini atau AOP. Ambient Context harus menjadi pilihan terakhir karena kliennya menyembunyikan ketergantungan mereka melaluinya. Saya masih akan menggunakan Ambient Context jika antarmuka itu benar-benar meniru dorongan saya untuk menggunakan dependensi statis seperti DateTime.Now
atau ConfigurationManager.AppSettings
dan kebutuhan ini meningkat cukup sering. Tetapi pada akhirnya injeksi konstruktor mungkin bukan ide yang buruk untuk mendapatkan dependensi di mana-mana.
IService
digunakan untuk berkomunikasi dengan layanan lain?" JikaIService
mewakili ketergantungan samar pada layanan lain maka itu terdengar seperti pencari lokasi dan seharusnya tidak ada. Kelas Anda harus bergantung pada antarmuka yang secara eksplisit menggambarkan apa yang akan dilakukan konsumen dengan mereka. Tidak ada kelas yang membutuhkan layanan untuk menyediakan akses ke layanan. Kelas membutuhkan ketergantungan yang melakukan sesuatu yang spesifik yang dibutuhkan kelas.