ที่จริงแล้ววิธี "ถูกต้อง" คือการไม่ใช้โรงงานเลยเว้นแต่จะไม่มีทางเลือกอื่น (เช่นในการทดสอบหน่วยและ mocks บางอย่าง - สำหรับรหัสการผลิตที่คุณไม่ได้ใช้โรงงาน)! การทำเช่นนี้เป็นรูปแบบการต่อต้านจริงและควรหลีกเลี่ยงค่าใช้จ่ายทั้งหมด จุดทั้งหมดที่อยู่เบื้องหลังคอนเทนเนอร์ DI คือการอนุญาตให้แกดเจ็ตทำงานให้คุณได้
ตามที่ระบุไว้ข้างต้นในโพสต์ก่อนหน้านี้คุณต้องการให้แกดเจ็ต IoC ของคุณรับผิดชอบในการสร้างออบเจ็กต์ที่ต้องพึ่งพาต่างๆในแอปของคุณ นั่นหมายถึงการปล่อยให้แกดเจ็ต DI ของคุณสร้างและจัดการอินสแตนซ์ต่างๆ นี่คือจุดรวมที่อยู่เบื้องหลัง DI - วัตถุของคุณไม่ควรรู้วิธีการสร้างและ / หรือจัดการวัตถุที่พวกเขาต้องพึ่งพา ที่จะทำอย่างอื่นแบ่งการมีเพศสัมพันธ์หลวม
การแปลงแอปพลิเคชั่นที่มีอยู่ให้กับ DI ทั้งหมดเป็นขั้นตอนใหญ่ แต่การแยกปัญหาที่ชัดเจนในการทำเช่นนั้นคุณจะต้อง (เพื่อทำให้ชีวิตของคุณง่ายขึ้น) เพื่อสำรวจเครื่องมือ DI ที่จะทำการผูกเป็นกลุ่มโดยอัตโนมัติ (หลักสำคัญของสิ่งที่คล้ายกับ Ninject คือการ"kernel.Bind<someInterface>().To<someConcreteClass>()"
เรียกที่คุณทำเพื่อให้ตรงกับการประกาศส่วนต่อประสานกับคลาสที่เป็นรูปธรรมที่คุณต้องการใช้เพื่อใช้อินเทอร์เฟซเหล่านั้นมันคือการเรียก "Bind" ที่อนุญาตให้ gadget ของคุณ อินสแตนซ์ของวัตถุที่จำเป็นต้องพึ่งพาตัวสร้างทั่วไป (รหัสหลอกที่แสดงที่นี่) สำหรับบางคลาสอาจเป็น:
public class SomeClass
{
private ISomeClassA _ClassA;
private ISomeOtherClassB _ClassB;
public SomeClass(ISomeClassA aInstanceOfA, ISomeOtherClassB aInstanceOfB)
{
if (aInstanceOfA == null)
throw new NullArgumentException();
if (aInstanceOfB == null)
throw new NullArgumentException();
_ClassA = aInstanceOfA;
_ClassB = aInstanceOfB;
}
public void DoSomething()
{
_ClassA.PerformSomeAction();
_ClassB.PerformSomeOtherActionUsingTheInstanceOfClassA(_ClassA);
}
}
โปรดทราบว่าไม่มีรหัสใดในรหัสที่สร้าง / จัดการ / นำออกใช้ทั้งอินสแตนซ์ของ SomeConcreteClassA หรือของ SomeOtherConcreteClassB ตามความเป็นจริงแล้วไม่มีการอ้างอิงชั้นรูปธรรมเลยแม้แต่น้อย ดังนั้น ... เวทมนตร์เกิดขึ้นที่ไหน?
ในส่วนเริ่มต้นของแอพของคุณสิ่งต่อไปนี้เกิดขึ้น (อีกครั้งนี่คือรหัสหลอก แต่มันค่อนข้างใกล้เคียงกับของจริง (Ninject) ... ):
public void StartUp()
{
kernel.Bind<ISomeClassA>().To<SomeConcreteClassA>();
kernel.Bind<ISomeOtherClassB>().To<SomeOtherConcreteClassB>();
}
โค้ดที่นิดหน่อยนั้นบอกให้ Gadget ของ Ninject ค้นหาตัวสร้างสแกนหาอินสแตนซ์ของอินเทอร์เฟซที่ได้รับการกำหนดค่าให้จัดการ (นั่นคือการเรียก "Bind") จากนั้นสร้างและแทนที่อินสแตนซ์ของคลาสคอนกรีต มีการอ้างอิงอินสแตนซ์
มีเครื่องมือที่ดีที่เติมเต็ม Ninject ที่เรียกว่า Ninject.Extensions.Conventions (ยังเป็นแพ็คเกจ NuGet อื่น) ที่จะทำงานนี้ให้คุณเป็นกลุ่ม ไม่ให้ห่างจากประสบการณ์การเรียนรู้ที่ยอดเยี่ยมที่คุณจะทำเมื่อคุณสร้างมันขึ้นมาด้วยตัวคุณเอง แต่เพื่อเริ่มต้นด้วยตัวคุณเองนี่อาจเป็นเครื่องมือในการตรวจสอบ
หากหน่วยความจำรองรับ Unity (จาก Microsoft อย่างเป็นทางการในขณะนี้เป็นโครงการโอเพ่นซอร์ส) มีการเรียกเมธอดหรือสองวิธีที่ทำสิ่งเดียวกันเครื่องมืออื่นมีตัวช่วยที่คล้ายกัน
ไม่ว่าเส้นทางไหนที่คุณเลือกอ่านหนังสือของ Mark Seemann สำหรับการฝึกอบรม DI ของคุณอย่างแน่นอนอย่างไรก็ตามมันควรจะชี้ให้เห็นว่าแม้แต่ "Great Ones" ของโลกวิศวกรรมซอฟต์แวร์ (เช่น Mark) สามารถสร้างข้อผิดพลาดที่ชัดเจน - Mark ลืมทั้งหมด Ninject ในหนังสือของเขาดังนั้นนี่คือแหล่งข้อมูลอื่นที่เขียนขึ้นเพื่อ Ninject ฉันมีมันและอ่านที่ดี: การเรียนรู้การฉีดเพื่อการพึ่งพา