1. DependencyInjection 개요

더보기

✔️  Singleton 주입

  • Logger 같은 전역 서비스(Singleton)를 ViewModel에 안전하게 주입하여 사용합니다.
  • MVVM에서 Logger.Instance를 직접 참조하지 않고, 인터페이스 기반으로 느슨한 결합을 유지합니다.

 

✔️ "Singleton 주입"을, DependencyInjection 기반으로 확장

  • App.xaml.cs에서 DI 컨테이너를 구성하고,
  • ILoggerService를 싱글톤으로 등록해 MainViewModel, SubViewModel에 자동으로 주입됩니다.
  • App.xaml.cs에서 ServiceCollection을 구성하고 ILoggerService, MainViewModel, SubViewModel을 등록
  • MainWindow.xaml.cs, SubWindow.xaml.cs에서 Ioc.Default.GetRequiredService<T>()로 ViewModel 주입
  • ViewModel 생성자는 그대로 ILoggerService를 받음

 

 

 

 

 

2. 예제1

더보기

📁 Message 구현

WPF_Singleton04_03MVVM/
├── Messages/
│ ├── LogUpdateMessage.cs
//├── Services/
//│ ├── ILoggerService.cs
//│ └── Logger.cs ← Singleton 구현
//├── ViewModels/
//│ └── MainViewModel.cs
//│ └── SubViewModel.cs
//├── Views/
//│ └── MainWindow.xaml
//│ └── MainWindow.xaml.cs
//│ └── SubWindow.xaml
//│ └── SubWindow.xaml.cs
//└── App.xaml.cs


✔️ LogUpdateMessage 메시지 
구현

// 메시지 정의
public class LogUpdateMessage : ValueChangedMessage<string>
{
public LogUpdateMessage(string value) : base(value) { }
}

 

 


 

📁 Services 구현

WPF_Singleton04_03MVVM/
//├── Messages/
//│ ├── LogUpdateMessage.cs
├── Services/
│ ├── ILoggerService.cs
│ └── Logger.cs ← Singleton 구현
//├── ViewModels/
//│ └── MainViewModel.cs
//│ └── SubViewModel.cs
//├── Views/
//│ └── MainWindow.xaml
//│ └── MainWindow.xaml.cs
//│ └── SubWindow.xaml
//│ └── SubWindow.xaml.cs
//└── App.xaml.cs

 

✔️ ILoggerService 인터페이스 구현

public interface ILoggerService
{
void Log(string message);
string GetLogs();
}

 

✔️ Logger 클래스 구현

public sealed class Logger : ILoggerService
{
private static Logger? _instance = null;
private static readonly object _lock = new();
private readonly StringBuilder _logs = new();
private Logger()
{
Console.WriteLine("Logger 인스턴스가 생성되었습니다.");
}
public static Logger Instance
{
get
{
lock (_lock)
{
return _instance ??= new Logger();
}
}
}
public void Log(string message)
{
string log = $"{DateTime.Now:HH:mm:ss} - {message}";
_logs.AppendLine(log);
// 로그가 업데이트되면 메시지를 발송하여 ViewModel에 알림
WeakReferenceMessenger.Default.Send(new LogUpdateMessage(_logs.ToString()));
}
public string GetLogs()
{
return _logs.ToString();
}
}

 

 

 


 

📁 ViewModel 구현

WPF_Singleton04_03MVVM/
//├── Messages/
//│ ├── LogUpdateMessage.cs
//├── Services/
//│ ├── ILoggerService.cs
//│ └── Logger.cs ← Singleton 구현
├── ViewModels/
│ └── MainViewModel.cs
│ └── SubViewModel.cs
//├── Views/
//│ └── MainWindow.xaml
//│ └── MainWindow.xaml.cs
//│ └── SubWindow.xaml
//│ └── SubWindow.xaml.cs
//└── App.xaml.cs

 

✔️ MainViewModel 구현

public partial class MainViewModel : ObservableObject
{
private readonly ILoggerService _logger;
[ObservableProperty]
private string logText;
public MainViewModel(ILoggerService logger)
{
_logger = logger;
_logger.Log("MainWindow 열림");
LogText = _logger.GetLogs();
// 메시지 수신 등록
WeakReferenceMessenger.Default.Register<LogUpdateMessage>(this, (r, m) =>
{
LogText = m.Value;
});
}
[RelayCommand]
private void WriteLog()
{
_logger.Log("MainWindow에서 로그 기록");
var logs = _logger.GetLogs();
LogText = logs;
WeakReferenceMessenger.Default.Send(new LogUpdateMessage(logs));
}
[RelayCommand]
private void OpenSubWindow()
{
var sub = new SubWindow();
sub.Show();
}
}

 

✔️ SubViewModel 구현

public partial class SubViewModel : ObservableObject
{
private readonly ILoggerService _logger;
[ObservableProperty]
private string logText;
public SubViewModel(ILoggerService logger)
{
_logger = logger;
_logger.Log("SubWindow 열림");
LogText = _logger.GetLogs();
WeakReferenceMessenger.Default.Register<LogUpdateMessage>(this, (r, m) =>
{
LogText = m.Value;
});
}
[RelayCommand]
private void WriteLog()
{
_logger.Log("SubWindow에서 로그 기록");
var logs = _logger.GetLogs();
LogText = logs;
WeakReferenceMessenger.Default.Send(new LogUpdateMessage(logs));
}
}

 

 

 

 

📁 View 구현

WPF_Singleton04_03MVVM/
//├── Messages/
//│ ├── LogUpdateMessage.cs
//├── Services/
//│ ├── ILoggerService.cs
//│ └── Logger.cs ← Singleton 구현
//├── ViewModels/
//│ └── MainViewModel.cs
//│ └── SubViewModel.cs
├── Views/
│ └── MainWindow.xaml
│ └── MainWindow.xaml.cs
│ └── SubWindow.xaml
│ └── SubWindow.xaml.cs
//└── App.xaml.cs

 

✔️ MainWindow.xaml 구현

Title="MainWindow" Height="300" Width="400">
<StackPanel Margin="10">
<Button Content="로그 남기기" Command="{Binding WriteLogCommand}" Margin="0 0 0 10"/>
<Button Content="SubWindow 열기" Command="{Binding OpenSubWindowCommand}" Margin="0 0 0 10"/>
<TextBox Text="{Binding LogText}" AcceptsReturn="True" Height="200" VerticalScrollBarVisibility="Auto"/>
</StackPanel>

 

✔️ MainWindow.xaml.cs 구현

public MainWindow()
{
InitializeComponent();
//DataContext = new MainViewModel(Logger.Instance);
DataContext = Ioc.Default.GetService<MainViewModel>();
}

 

 

✔️ SubWindow 구현

Title="SubWindow" Height="250" Width="350">
<StackPanel Margin="10">
<Button Content="로그 남기기" Command="{Binding WriteLogCommand}" Margin="0 0 0 10"/>
<TextBox Text="{Binding LogText}" AcceptsReturn="True" Height="150" VerticalScrollBarVisibility="Auto"/>
</StackPanel>

 

✔️ SubWindow.xaml.cs 구현

public SubWindow()
{
InitializeComponent();
//DataContext = new SubViewModel(Logger.Instance);
DataContext = Ioc.Default.GetService<SubViewModel>();
}

 

 

 


📁
 Services
 구현

WPF_Singleton04_03MVVM/
//├── Messages/
//│ ├── LogUpdateMessage.cs
//├── Services/
//│ ├── ILoggerService.cs
//│ └── Logger.cs ← Singleton 구현
//├── ViewModels/
//│ └── MainViewModel.cs
//│ └── SubViewModel.cs
//├── Views/
//│ └── MainWindow.xaml
//│ └── MainWindow.xaml.cs
//│ └── SubWindow.xaml
//│ └── SubWindow.xaml.cs
└── App.xaml.cs

 

✔️ App.xaml.cs 구현

protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// IoC 컨테이너에 싱글톤 Logger 등록
Ioc.Default.ConfigureServices(
new ServiceCollection()
.AddSingleton<ILoggerService>(Logger.Instance)
.AddTransient<MainViewModel>()
.AddTransient<SubViewModel>()
.BuildServiceProvider()
);
var mainWindow = new MainWindow();
mainWindow.Show();
}

 

 

 

✔️ 소스코드

 

WPF_IoC.zip
0.11MB