종속성은 다른 개체가 의존하는 개체입니다. 종속성 주입(또는 반전)은 기본적으로 개체 자체를 구성하는 대신 개체에 필요한 개체를 제공합니다. 종속성을 모의할 수 있으므로 테스트를 더 쉽게 만드는 유용한 기술입니다.
예를 들어 클래스 A가 클래스 B의 메서드를 호출하고 이 메서드가 클래스 C의 메서드를 호출하면 A는 B에 종속되고 B는 C에 종속됨을 의미합니다. 종속성 주입을 사용하여 클래스 C의 인스턴스를 클래스 B에 전달할 수 있습니다. , 그리고 B와 C의 인스턴스를 구성하기 위해 이러한 클래스를 사용하는 대신 B의 인스턴스를 클래스 A에 전달합니다.
아래 예제에서 Runner 클래스는 Logger 클래스에 종속됩니다. Runner 클래스에서 생성자에서 Logger의 인스턴스를 생성한다는 점에 유의하십시오. 이 코드에는 몇 가지 문제가 있습니다.
-
이것은 로거 클래스를 Runner에 연결하며 Runner를 수정하지 않고는 다른 클래스로 대체할 수 없습니다.
-
Logger에 종속성이 있는 경우 작업자는 Logger를 인스턴스화하기 전에 종속성을 구성해야 합니다.
-
테스트가 더 어렵습니다. Logger가 네트워크 또는 파일 시스템에 액세스하는 것과 같이 리소스를 많이 사용하는 클래스인 경우 테스트 속도가 느려집니다. 쉽게 교체할 수 없습니다.
using System; class Program{ static void Main(string[] args){ var runner = new Runner(); runner.Run(); } } class Runner{ private Logger _logger; public Runner(){ _logger = new Logger(); } public void Run(){ // Do some work _logger.Log("Message to be logged"); } } class Logger{ public void Log(string message){ Console.WriteLine(message); } }
종속성 주입을 사용하여 구체적인 개체 대신 ILogger 인터페이스를 허용하도록 Runner의 생성자를 수정합니다. ILogger를 구현하기 위해 Logger 클래스를 변경합니다. 이를 통해 Logger 클래스의 인스턴스를 Runner의 생성자에 전달할 수 있습니다. 이것의 이점은 테스트 중에 ILogger를 구현하는 TestLogger 클래스를 만들고 이를 Runner의 생성자에 전달할 수 있다는 것입니다.
예
using System; class Program{ static void Main(string[] args){ var logger = new Logger(); var runner = new Runner(logger); runner.Run(); } } class Runner{ private ILogger _logger; public Runner(ILogger logger){ _logger = logger; } public void Run(){ // Do some work _logger.Log("Message to be logged"); } } interface ILogger{ void Log(string message); } class Logger : ILogger{ public void Log(string message){ Console.WriteLine(message); } }
출력
Message to be logged