Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

การอธิบาย Dependency Injection ใน C#


Dependency (การอาศัย) คือออบเจกต์ที่ออบเจกต์อื่นต้องพึ่งพา Dependency Injection (DI) หรือ Inversion of Control คือการจัดหาออบเจกต์ที่จำเป็นให้กับออบเจกต์แทนที่จะให้ออบเจกต์สร้างเอง เทคนิคนี้ทำให้การทดสอบ (Testing) ง่ายขึ้น เพราะสามารถ Mock dependencies ได้

ตัวอย่าง: ถ้าคลาส A เรียกเมธอดของคลาส B ซึ่งเรียกเมธอดของคลาส C แสดงว่า A depends on B และ B depends on C ด้วย DI เราส่ง instance ของ C ให้ B และส่ง instance ของ B ให้ A แทนที่จะให้สร้างเอง

ในตัวอย่างก่อนหน้า คลาส Runner มี dependency กับ Logger สังเกตว่า Runner สร้าง Logger เองใน Constructor มีปัญหา 3 ข้อ:

  • ผูกมัด Logger กับ Runner ไม่สามารถเปลี่ยนเป็นคลาสอื่นได้โดยไม่แก้ Runner
  • ถ้า Logger มี dependencies ของตัวเอง Runner ต้องจัดการให้
  • ทดสอบยาก หาก Logger ใช้ทรัพยากรมาก (Network, File) จะช้าและแทนที่ไม่ได้ง่าย
// ก่อนใช้ DI - Tight Coupling
class Runner
{
    private Logger _logger;
    public Runner() { _logger = new Logger(); }
    public void Run() { _logger.Log("Message"); }
}
class Logger { public void Log(string msg) { Console.WriteLine(msg); } }

ใช้ DI: แก้ Constructor ของ Runner รับ Interface ILogger แทน Concrete Class เปลี่ยน Logger ให้ implement ILogger สามารถส่ง Logger instance ให้ Runner ผ่าน Constructor ระหว่างทดสอบ สร้าง TestLogger implement ILogger ส่งให้ Runner แทน

ตัวอย่างหลังใช้ DI

interface ILogger { void Log(string message); }
class Logger : ILogger { public void Log(string msg) { Console.WriteLine(msg); } }

class Runner
{
    private ILogger _logger;
    public Runner(ILogger logger) { _logger = logger; }
    public void Run() { _logger.Log("Message to be logged"); }
}

class Program
{
    static void Main()
    {
        var logger = new Logger();
        var runner = new Runner(logger);
        runner.Run();
    }
}

ผลลัพธ์

Message to be logged