แก้ไขข้อผิดพลาดการพึ่งพาแบบวงกลมโดยใช้ DI ใน. net core [ซ้ำกัน]

ฉันกำลังประสบปัญหาเกี่ยวกับข้อผิดพลาดในการอ้างอิงการขึ้นต่อกันแบบวงกลมในเว็บแอป .net core แม้ว่าฉันคิดว่าฉันเข้าใจปัญหาแล้ว ฉันไม่สามารถคิดถึงวิธีแก้ไขปัญหาที่ฉันเผชิญได้ แต่ฉันได้ค้นหาไปรอบๆ แล้วและดูเหมือนจะไม่พบใครที่มีปัญหาเดียวกันอีกเลย

นี่คือโฟลว์ลอจิกที่ฉันพยายามทำให้สำเร็จ: 1. พื้นที่เก็บข้อมูลทั่วไปที่จัดการการดำเนินการ db CRUD 2. ภายในพื้นที่เก็บข้อมูลนี้มีบริการที่ทำงานบางอย่างตามประเภทของการดำเนินการฐานข้อมูลที่เกิดขึ้น

ตัวอย่างที่ 1 มีการแทรกบันทึกใหม่ลงในตารางผู้ใช้ มีงานที่ทริกเกอร์อีเมลต้อนรับถึงผู้ใช้

ตัวอย่างที่ 2 ลูกค้าเป้าหมายถูกแทรกลงในฐานข้อมูล มีงานที่สร้างงานติดตามผลสำหรับผู้ดูแลระบบ

เหตุผลที่จัดการทั้งหมดนี้ด้วยวิธีทั่วไปก็คือฉันต้องการจัดเตรียมอินเทอร์เฟซสำหรับผู้ดูแลระบบแอปเพื่อสร้าง/อัปเดตงานทริกเกอร์เหล่านี้ ดังนั้นในตัวอย่างที่ 1 เหตุใดฉันจึงไม่เพียงแค่ฮาร์ดโค้ดอีเมลถึงผู้ใช้

ฉันใช้ DI เพื่อแก้ไขปัญหาบริการต่างๆ และปัญหาที่ฉันมีมีดังนี้:

EntityFrameworkRepository ใช้ IRepository ป้อนคำอธิบายรูปภาพที่นี่

ตัวสร้าง TriggerService ป้อนคำอธิบายรูปภาพที่นี่

ITriggerService ถูกฉีดเข้าไปใน EntityFrameworkRepository ข้อผิดพลาดเกิดขึ้นเนื่องจากฉันพยายามฉีดและแก้ไข IRepository ในบริการทริกเกอร์ แม้ว่าจะไม่มี templateService การฉีดนี้ก็พยายามแก้ไข IRepository ในตัวสร้างของตัวเองเช่นกัน ในตอนนี้ ฉันเพิ่งเข้ารหัส ITempalteService และ IEmailerService แต่จะมี 'บริการการดำเนินการทริกเกอร์' อื่นๆ อีกมากมายที่จะนำไปใช้ตลอดทั้งโค้ดและบริการอื่นๆ ดังนั้นฉันจึงไม่ต้องการเปลี่ยนแปลงการออกแบบสิ่งเหล่านี้จริงๆ

ฉันรับรู้ว่านี่เป็นการออกแบบที่ไม่ดีโดยอิงจากคนอื่นๆ ทั้งหมดที่ถามคำถามที่คล้ายกันและคำตอบที่พวกเขาได้รับ สิ่งที่ฉันไม่สามารถเข้าใจได้คือวิธีแก้ไข/ออกแบบโซลูชันที่ถูกต้องเพื่อให้บรรลุเป้าหมายที่ต้องการ

ยินดีรับข้อเสนอแนะทั้งหมด!


person James    schedule 25.01.2018    source แหล่งที่มา
comment
ทำไมคุณถึงต้องการคุณสมบัติ IRepository ใน TriggerService   -  person Krishna Mohan    schedule 25.01.2018
comment
อ่านการดำเนินการทริกเกอร์จาก db บริการเทมเพลตยังอ่านเทมเพลตจาก db เพื่อใช้ในบริการอีเมล   -  person James    schedule 25.01.2018
comment
ฉันคิดว่าเป็นการดีกว่าที่จะเรียกใช้ triggerService จาก Controller/BusinessLayer (ตามโครงสร้างโซลูชันของคุณ) หากต้องการใช้ EntityFrameworkRepository ใน TriggerService คุณสามารถ DI ใน Startup.cs   -  person Krishna Mohan    schedule 25.01.2018
comment
โดยไม่คำนึงถึงการพึ่งพาแบบวงกลม ซึ่งคุณสามารถแก้ไขได้เช่นการใช้เหตุการณ์ (ตามที่อธิบายไว้ในคำถามที่เชื่อมโยง): ดูเหมือนไม่ถูกต้องที่ พื้นที่เก็บข้อมูลฐานข้อมูล มีหน้าที่รับผิดชอบในการเรียกอีเมลต้อนรับหรือสิ่งอื่น ๆ ข้อกังวลเพียงอย่างเดียวของพื้นที่เก็บข้อมูลคือการเข้าถึงฐานข้อมูล หากมีการดำเนินการ “สร้างผู้ใช้และทริกเกอร์อีเมลต้อนรับ” การดำเนินการนั้นควรไปที่บริการแยกต่างหาก โดยแนะนำเลเยอร์อื่น ดังนั้น คุณจะใช้ “บริการผู้ใช้” ซึ่งสร้างเอนทิตีโดยใช้พื้นที่เก็บข้อมูลของคุณ จากนั้นทริกเกอร์อีเมลต้อนรับโดยใช้บริการทริกเกอร์   -  person poke    schedule 25.01.2018


คำตอบ (1)


โดยทั่วไป พื้นที่เก็บข้อมูลควรทำเฉพาะการดำเนินการ CRUD ที่โง่เขลา โดยไม่มี ตรรกะทางธุรกิจใดๆ แน่นอนว่าการส่งอีเมลและสร้างงานติดตามผลเมื่อมีการแทรกบันทึกเป็นตรรกะทางธุรกิจ

ลองนึกภาพว่าคุณจำเป็นต้องอนุญาตให้แทรกบันทึกโดยไม่ต้องส่งอีเมลต้อนรับ เนื่องจากมีการแนะนำกรณีการใช้งานใหม่ และกรณีการใช้งานดังกล่าวไม่เกี่ยวข้องกับจุดประสงค์เดิม ตัวอย่างง่ายๆ คือผู้ใช้ประเภทที่ไม่ต้องการรับการแจ้งเตือน กล่าวอีกนัยหนึ่ง หากคุณเดินสายตรรกะทางธุรกิจบางอย่างกับการดำเนินการที่เก็บข้อมูล คุณจะไม่สามารถแยกออกได้เมื่อจำเป็น

วิธีที่ถูกต้องในการคิดถึงปัญหาของคุณคือการเรียบเรียงใหม่ โดยแปลง repo + ตรรกะทางธุรกิจแบบผสมให้เป็นตรรกะทางธุรกิจล้วนๆ:

  1. บันทึกใหม่ถูกแทรกลงในตารางผู้ใช้ มีงานที่ทริกเกอร์อีเมลต้อนรับถึงผู้ใช้ => ลงทะเบียนผู้ใช้ใหม่แล้ว มีงานที่ทริกเกอร์อีเมลต้อนรับถึงผู้ใช้
  2. ลูกค้าเป้าหมายถูกแทรกลงในฐานข้อมูล มีงานที่สร้างงานติดตามผลสำหรับผู้ดูแลระบบ => ลูกค้าเป้าหมายถูกสร้างขึ้น มีงานที่สร้างงานติดตามผลสำหรับผู้ดูแลระบบ

เมื่อพูดถึงโค้ด คำแนะนำของฉันคือเพิ่มบริการระดับกลางที่เรียกใช้พื้นที่เก็บข้อมูลเพื่อดำเนินการ CRUD เปล่า และ เรียกใช้บริการที่ให้ผลข้างเคียงที่ต้องการ

เมื่อพิจารณาตัวอย่างที่ 1 ของคุณ (ตัวอย่างที่ 2 ในทำนองเดียวกัน) แทนที่จะเรียก IRepository โดยตรงเพื่อแทรกบันทึกผู้ใช้ ให้ฉีด IUserService ใหม่ให้กับผู้เรียก ซึ่งจะได้รับ IRepository และ IEmailerService ในตัวสร้างและเรียกพวกเขา ซึ่งจะทำให้คุณสามารถแทรก IRepository ลงใน IEmailerService ได้โดยไม่มีปัญหา

สิ่งเดียวที่ฉันไม่สามารถบอกคุณได้คือว่าคำแนะนำของฉันสามารถนำไปใช้ตามความต้องการของคุณในการจัดหาอินเทอร์เฟซทั่วไปได้หรือไม่ อย่างไรก็ตาม การปรับโครงสร้างใหม่ที่จำเป็นเพื่อใช้การเปลี่ยนแปลงดังกล่าวควรให้ผลน้อยที่สุด และแน่นอนว่าปัญหาการพึ่งพาแบบวงกลม (ที่เกิดจากความเป็นวงกลมในสูตรดั้งเดิม) จะได้รับการแก้ไขแล้ว

person FstTesla    schedule 25.01.2018