Updated at 2021.6.7
Dependency Injection
Dependency Injection는 종속성 주입
또는 의존성 주입
이라고 하는데, 클래스를 설계할 때 두 개 이상의 클래스 사이의 관계를 설정하는 방법이다.
클래스 관계 설정
프로그래밍에서 많이 맞딱들이는 상황이 어떤 클래스에서 다른 클래스를 사용하고자 할 때 어떻게 할 것인가 이다.
예를 들어 아래와 같이 ClassB
에서 ClassA
를 초기화하여 사용하면 ClassA를 변경하고자 할 때 코드를 직접 수정하지 않으면 안된다.
class ClassA {
public string Name { get; set;}
public void SetAndPrintOut(string firstName, string familyName)
{
Name = $"{firstName}, {familyName}";
Console.WriteLine(Name);
}
}
class ClassB {
private ClassA _classA = new();
public void PrintOut(string firstName)
{
_classA.SetAndPrintOut(firstName, "Kim");
}
}
더구나 아래의 다이어그램과 같이 ClassA
와 유사한 클래스(ClassAA
등)나 객체가 많아서 그것을 ClassB
에서 사용하고자 한다면 어떻게 하면 될까?
인터페이스와 종속성 주입
아래의 다이어그램과 같은 방식으로 종속성 주입을 활용하면 이러한 문제를 해결할 수 있다.
위의 코드를 아래와 같이 수정하면 ClassA
가 변경되어도 ClassB
를 다시 코딩할 필요가 없다. 즉 느슨하게 결합 (Loosely Coupled)된 코딩을 할 수 있다.
- 인터페이스(Interface)
IClassA
선언 - 인터페이스를 상속받는
ClassA
선언 ClassB
에서IClass
를 내부 필드(Field)로 선언하고,생성자
에서 변수를 입력 받아서 대입
interface IClassA {
string Name { get; set;}
void SetAndPrintOut(string firstName, string familyName);
}
class ClassA: IClassA {
public string Name { get; set;}
public void SetAndPrintOut(string firstName, string familyName)
{
Name = $"{firstName}, {familyName}";
Console.WriteLine(Name);
}
}
class ClassB {
private readonly IClassA _classA;
public ClassB(IClassA classA)
{
_classA = classA;
}
public void PrintOut(string firstName)
{
_classA.SetAndPrintOut(firstName, "Kim");
}
}
ASP.NET에서의 종속성 주입이란?
웹코딩에서 글로벌 변수로 선언하여 모든 하위 웹에서 그 객체를 공용으로 사용하고 싶을 때 어떻게 할 것인가? ASP.NET에서는 Startup
클래스의 ConfigureServices
함수내에서 IServiceCollection
의 사용할 수 있는 다음과 같은 3가지 함수를 제공한다.
서비스 수명에 따라 선택해서 사용하면 된다. Server를 기준으로 간단히 정리해 보면 다음과 같다.
수명 | 설명 |
---|---|
Transient | 요청할 때마다 |
Scoped | 새 창을 열고 다시 접속할 때마다 또는 새로 고침할 때마다 |
Singletone | 처음 시작할 때만 |
실제 코딩에서의 사용법은 다음과 같다.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ClassA>();
services.AddSingleton<IClassA, ClassA>();
}
}
파라미터를 가지고 종속성 주입하기
ClassA
의 생성자가 파라미터를 가지고 있는 경우, 그리고 그 파라미터도 서비스로 등록이 되어 있는 경우에는 어떻게 할 것인가? 즉 글로벌 객체를 인자로 가지는 글로벌 객체를 선언해야 할 경우이다.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IClassA, ClassA>();
services.AddSingleton(x => new ClassB(x.GetService<IClassA, ClassA>()));
}
}
댓글
댓글 쓰기