Atasi kesalahan ketergantungan melingkar menggunakan DI di .net core [duplikat]

Saya menghadapi masalah dengan kesalahan referensi ketergantungan melingkar di aplikasi web inti .net. Meskipun saya pikir saya memahami masalahnya, saya tidak dapat memikirkan solusi untuk masalah yang saya hadapi, saya telah mencari-cari dan sepertinya juga tidak menemukan orang lain yang mengalami masalah yang sama.

Ini adalah alur logika yang ingin saya capai: 1. Repositori generik yang menangani operasi db CRUD. 2. Di dalam repositori ini terdapat layanan yang melakukan tugas tertentu berdasarkan jenis tindakan db yang terjadi.

Contoh 1 Sebuah record baru disisipkan ke tabel pengguna, ada tugas yang memicu email selamat datang kepada pengguna.

Contoh 2 Sebuah lead dimasukkan ke database, ada tugas yang membuat tugas tindak lanjut untuk admin sistem.

Alasan mengapa semua ini ditangani dengan cara yang umum adalah karena saya ingin menyediakan antarmuka bagi admin aplikasi untuk membuat/memperbarui tugas pemicu ini, maka dalam contoh 1 mengapa saya tidak hanya membuat kode keras email ke pengguna.

Saya menggunakan DI untuk menyelesaikan berbagai layanan dan masalah yang saya alami adalah sebagai berikut:

EntityFrameworkRepository mengimplementasikan IRepository masukkan deskripsi gambar di sini

Konstruktor TriggerService masukkan deskripsi gambar di sini

ITriggerService disuntikkan ke EntityFrameworkRepository, kesalahan dipicu karena saya kemudian mencoba menyuntikkan dan menyelesaikan IRepository di layanan pemicu, bahkan tanpa templateService injeksi ini juga mencoba menyelesaikan IRepository di konstruktornya sendiri. Saat ini saya hanya memiliki kode ITempalteService dan IEmailerService tetapi akan ada banyak 'layanan tindakan pemicu' lainnya yang juga akan digunakan di seluruh kode dan layanan lainnya jadi saya tidak benar-benar ingin mengubah desainnya.

Saya menyadari bahwa ini adalah desain yang buruk berdasarkan semua orang yang telah mengajukan pertanyaan serupa dan tanggapan yang mereka terima, yang tidak dapat saya pahami adalah bagaimana menyelesaikan/merancang solusi yang tepat untuk mencapai tujuan yang diinginkan.

Semua saran diterima!


person James    schedule 25.01.2018    source sumber
comment
Mengapa Anda memerlukan properti IRepository di TriggerService?   -  person Krishna Mohan    schedule 25.01.2018
comment
Ia membaca tindakan pemicu dari db, layanan templat juga membaca templat dari db untuk digunakan dalam layanan email   -  person James    schedule 25.01.2018
comment
Saya pikir lebih baik untuk memanggil triggerService dari Controller/BusinessLayer (sesuai struktur solusi Anda). Untuk menggunakan EntityFrameworkRepository di TriggerService, Anda dapat melakukannya di Startup.cs   -  person Krishna Mohan    schedule 25.01.2018
comment
Terlepas dari ketergantungan melingkar, yang dapat Anda selesaikan misalnya menggunakan peristiwa (seperti yang dijelaskan dalam pertanyaan tertaut): Tampaknya tidak benar bahwa repositori basis data bertanggung jawab untuk memicu email selamat datang atau hal-hal lain. Satu-satunya perhatian repositori adalah akses database. Jika ada tindakan “buat pengguna dan picu email selamat datang”, maka tindakan tersebut sebaiknya dimasukkan ke layanan terpisah, dengan memperkenalkan lapisan lain. Jadi Anda akan menggunakan "layanan pengguna" yang kemudian membuat entitas menggunakan repositori Anda, dan kemudian memicu email selamat datang menggunakan layanan pemicu.   -  person poke    schedule 25.01.2018


Jawaban (1)


Secara umum, repositori seharusnya hanya melakukan operasi CRUD yang bodoh, tanpa logika bisnis apa pun. Tentu saja, mengirim email dan membuat tugas tindak lanjut setelah penyisipan data merupakan logika bisnis.

Bayangkan Anda perlu mengizinkan penyisipan catatan tanpa mengirimkan email selamat datang, karena kasus penggunaan baru diperkenalkan, dan kasus penggunaan tersebut tidak terkait dengan maksud awal. Contoh sederhananya adalah pengguna yang tidak perlu menerima notifikasi. Dengan kata lain, jika Anda menghubungkan beberapa logika bisnis dengan operasi repositori, Anda tidak akan dapat melepaskannya bila diperlukan.

Cara yang tepat untuk memikirkan masalah Anda adalah dengan mengulanginya, mengubah repo campuran + logika bisnis menjadi logika bisnis murni:

  1. Catatan baru dimasukkan ke tabel pengguna, ada tugas yang memicu email selamat datang kepada pengguna. => Pengguna baru telah terdaftar, ada tugas yang memicu email selamat datang kepada pengguna.
  2. Prospek dimasukkan ke database, ada tugas yang membuat tugas tindak lanjut untuk admin sistem. => Prospek telah dibuat, ada tugas yang membuat tugas tindak lanjut untuk admin sistem.

Berbicara tentang kode, saran saya adalah menambahkan layanan perantara yang memanggil repositori untuk melakukan CRUD dan memanggil layanan yang memberikan efek samping yang diinginkan.

Mempertimbangkan contoh pertama Anda (yang kedua serupa), alih-alih memanggil IRepository secara langsung untuk memasukkan catatan pengguna, masukkan IUserService baru ke dalam pemanggil, yang pada gilirannya menerima IRepository dan IEmailerService di konstruktornya dan memanggilnya. Ini memungkinkan Anda memasukkan IRepository ke IEmailerService tanpa kesulitan.

Satu-satunya hal yang tidak dapat saya sampaikan kepada Anda adalah apakah saran saya dapat diterapkan sesuai dengan kebutuhan Anda untuk menyediakan antarmuka umum. Bagaimanapun, pemfaktoran ulang yang diperlukan untuk menerapkan perubahan tersebut harus menghasilkan hasil yang minimal, dan tentu saja masalah ketergantungan sirkular (yang disebabkan oleh sirkularitas dalam formulasi aslinya) dapat diatasi.

person FstTesla    schedule 25.01.2018