wpf 의존성 주입 컨테이너 관련 질문 있습니다.

  1. 보통 의존성 주입을 위해 서비스를 등록하고 GetRequiredService<>()를 통해 의존성 주입이 일어난다고 알고있는데 이 부분이 맞는지 알고싶습니다.

  2. 그리고 App.xmal의 코드 비하인드에서 DataContext = s.GetRequiredService() 이런식으로 의존성 주입을 한다면 MainViewModel 의 인스턴스가 생성되어 생성자가 호출되는것 같습니다.
    이때 MainViewModel의 생성자의 매개변수로
    public MainViewModel(MainNavigationStore mainNavigationStore, INavigationService navigationService) {} 이런식으로 들어가게 된다면 이 매개변수들은 앞서 서비스 등록과정에서 등록된 서비스라면 이런식으로 MainViewModel이 생성될 때 매개변수를 통해 의존성 주입이 일어나는 것인가요?

  3. services.AddSingleton(); 이런식으로 서비스를 등록할 때 서비스 등록이라는 개념이 아직 와닿지 않습니다. 서비스를 등록하고 해당 서비스를 의존성 주입할 때 그때 등록했던 서비스의 인스턴스가 생성되는건지, 서비스를 등록하면 이때 인스턴스가 생성되는건지 잘 모르겠습니다.

3개의 좋아요

IoC Container는 일종의 Factory입니다.
class라는 설계도를, 1개만 생성할지(AddSingleton), 세션 내에서는 공유할 것인지(AddScoped), 요청할 때마다 계속 새로운 인스턴스를 만들어낼 것인지(AddTransient)를 등록하는 시점에 결정합니다.

디버깅을 찍어보시면 아시겠지만 위의 메서드를 호출할 때는 Constructor를 타지않습니다. 아직 인스턴스 생성이 되는 단계가 아니기 때문입니다.

일반적으로 C#을 처음 배우고 IoC Container를 모를 때는

class A {}

A abc = new A();

위와 같은 방법으로 인스턴스를 생성합니다.
하지만 말씀하신 대로 GetRequiredService를 호출 할 때는 생성자의 인자들을 고려하지 않고 생성할 수 있게 됩니다.

아래 제가 과거에 적어둔 글을 참조하시면 좋을 것 같습니다.

이 때 생성자 주입이 발생하면서 IoC Container에 들어있던 class 들이 AddTransient, AddScoped, AddSingleton의 형태에 따라 새로운 인스턴스가 주입될 수도, 기존의 인스턴스가 주입될 수도 있습니다.

하지만 최초에 호출될 때 Lazy하게 호출되기 때문에 생성자가 호출되는 시점은 소스코드를 많이 돌려보시면서 직접 이해하시는 게 좋을 것 같습니다.

개념은 충분히 있으니 직접 예제코드를 만들어 보셔서 디버깅해보시는 해보시는 시간을 2시간 정도만 가져보시면 충분히 이해하실 수 있을 거라 생각합니다.

다만 WPF를 통해 Microsoft.Extensions.DependencyInjection을 처음 접하시는 분들에게는 AddScoped와 AddSingleton이 헷갈리 실 수 있습니다.

Microsoft.Extensions.DependencyInjection은 제가 알기로 맨 처음 ASPNET를 위해 설계되었기 때문에 웹을 고려하여 세션개념을 넣어서 만들었다고 알고 있기 때문입니다.
따라서 세션개념이 없는 Desktop Application인 경우 세션이 있다면 1개라고 생각할 수 있기 때문에 프로세스 내부에서 AddSingleton과 동일한 형태로 동작하게 됩니다.
이 부분만 이해해보시면 될 것 같고, 만약 이런게 마음에 들지 않으신다면 다른 IoC Container 로

등등이 있습니다.

4개의 좋아요

친절한 답변 감사합니다.
이것은 또 다른 질문인데 네비게이션 이라는게 보통 메뉴를 만들고(예를 들어 버튼을 누를 때 마다 다른 View 가 뜨도록 하기 위해) 의존성 주입을 통해 서로를 연결 시켜주는 것이 맞나요??

또한 이 각각의 View에 대응되는 ViewModel 들이 있을것이고 이 ViewModel간의 데이터 교환을 할 때 Messanger 를 이용하는것인가요??

2개의 좋아요

MVVM은 구현하기 나름입니다.

말씀하신대로 해도 안해도 됩니다.

Navigation에 대한 예제 소스가 궁금하시다면, ChatGPT에게 물어보시거나 TemplateStudio를 통해 NavigationView를 생성하셔서 오픈소스를 뜯어보시면 이해가 되실 것도 같습니다.

MVVM을 처음 접하면 여러 생소한 용어들이 나오면서 내가 기존에 해왔던 방식과 다르게 해야하는건가? 라는 망설임에 소스코드를 쉽게 수정할 수 없게되거나 확신이 들지 않아서 일을 할 수가 없게 됩니다.

따라서 너무 많이 고민하시기 보다는 일단은 진행하시면서 점점 조금씩 리펙토링을 하시는 것도 방법이라고 봅니다.

객체지향에 정답이 없고 트레이드오프를 통한 상황의 선택만 있듯, 객체지향의 확장된 개념인 MVVM 역시 Trade-Off는 존재하며 내가 의존성을 어디까지 줄지 가중치를 선택할 수 있습니다.

MVVM을 소개하는 개념과 자료들이 완성된 이론에 입각해 있기 때문에 완전히 느슨한 방식을 지향하도록 안내하고 있습니다.

이 경우에는 모든 컨셉이 느슨한 것이므로 Messenger를 사용하시는 게 맞겠지만, ViewModel간 의존성의 방향을 통해 직접적으로 객체의 Method에 Parameter를 입력해서 하는 방식도 있습니다.

이게 초보도 이해할 수 있는 일반적인 C# 의 코딩이죠.

제가 방향을 정해드리는 답변이 아니라 애매하게 말씀을 드리는 것처럼 보이시겠지만, 정답이 없다는 것이 정답입니다.

따라서 Messenger를 이용하셔도 되고, 이용하지 않으셔도 됩니다.
이용하지 않는다면 객체가 객체의 참조를 직접적으로 들고 있어서 C# 코딩하듯 하셔도 되고 이것이 틀린 방법이 아닙니다.

3개의 좋아요