[WPF] 의존성 주입(Dependency Injection)
이전 글에서는 WPF의 의존성 주입에 대해 알아보았고, 이번엔 직접 예제를 구현해 보는 시간!
.NET의 IoC 컨테이너인 `Microsoft.Extensions.DependencyInjection` 누겟을 사용한 예제이다.
• IDateTimeService.cs
DateTime 관련 서비스의 인터페이스로, 구상 클래스에서 구현해야 할 메서드를 정의했다
namespace DotNetDependencyInjection.Services
{
public interface IDateTimeService
{
string GetDateTimeString();
}
}
• DateTimeService.cs
IDateTimeService 인터페이스를 구현하는 클래스로, 현재 시간을 String값으로 리턴하는 메서드를 작성했다
namespace DotNetDependencyInjection.Services
{
public class DateTimeService : IDateTimeService
{
public string GetDateTimeString()
{
return DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
}
}
}
• App.xaml
WPF 프로젝트를 생성하면 App.xaml에 정의되어 있는 `StartupUri`를 지워준다
(`StartupUri="MainWindow.xaml"` → 삭제)
<Application
x:Class="DotNetDependencyInjection.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources />
</Application>
• App.xaml.cs
`OnStartUp` 메서드를 오버라이드하여 필요한 서비스들을 등록하고,
`MainWindow`를 찾아 Show 메서드로 호출해준다. (StartupUri와 유사한 역할)
using System.Windows;
using DotNetDependencyInjection.ViewModels;
using DotNetDependencyInjection.Services;
using DotNetDependencyInjection.Views;
using Microsoft.Extensions.DependencyInjection;
namespace DotNetDependencyInjection
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public IServiceProvider ServiceProvider { get; set; }
/// <summary>
/// OnStartup
/// </summary>
/// <param name="e"></param>
protected override void OnStartup(StartupEventArgs e)
{
var services = ConfigureServices();
ServiceProvider = services.BuildServiceProvider();
var mainWindow = ServiceProvider.GetRequiredService<MainWindow>();
mainWindow.Show();
}
/// <summary>
/// Configure Services
/// </summary>
/// <returns></returns>
private ServiceCollection ConfigureServices()
{
ServiceCollection serviceCollection = new();
serviceCollection.AddTransient<IDateTimeService, DateTimeService>();
serviceCollection.AddSingleton<MainWindowViewModel>();
serviceCollection.AddSingleton(s => new MainWindow()
{
DataContext = s.GetRequiredService<MainWindowViewModel>()
});
return serviceCollection;
}
}
}
등록할 서비스들은 각 서비스 성격에 따라 생명주기(Singleton, Scoped, Transient)를 설정한다.
또한 `MainWindow.xaml` 또는 `MainWindow.xaml.cs`에서 DataContext를 설정하지 않고, `GetRequiredService`를 사용해서 의존성이 주입된 `MainWindowViewModel`을 DataContext로 설정하는 것이 핵심!
• MainWindow.xaml
확인 버튼과 결과 텍스트가 있는 간단한 화면이다
<Window
x:Class="DotNetDependencyInjection.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:DotNetDependencyInjection.ViewModels"
Title="MainWindow"
Width="400"
Height="350"
d:DataContext="{d:DesignInstance Type=vm:MainWindowViewModel,
IsDesignTimeCreatable=False}"
mc:Ignorable="d">
<Grid Margin="30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock Text="현재 시간" />
<Button
Margin="5,0"
Command="{Binding ButtonClickCommand}"
Content="확인" />
</StackPanel>
<TextBlock
Grid.Row="1"
Margin="0,10"
FontSize="20"
Text="{Binding DateTimeString, Mode=TwoWay}" />
</Grid>
</Window>
• MainWindowViewModel.cs
결과값으로 보여줄 string 값과 Command가 정의된 뷰모델이고, 생성자 주입을 통한 의존성 주입을 구현했다.
`BindableBase`는 `Prism.Core` 누겟을 설치하면 상속받을 수 있다.
using DotNetDependencyInjection.Services;
using System.Windows.Input;
namespace DotNetDependencyInjection.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private readonly IDateTimeService _dateTimeService;
private string _dateTimeString = string.Empty;
/// <summary>
/// 시간 문자열
/// </summary>
public string DateTimeString
{
get => _dateTimeString;
set => SetProperty(ref _dateTimeString, value);
}
/// <summary>
/// Button Click Command
/// </summary>
public ICommand ButtonClickCommand { get; set; }
public MainWindowViewModel()
{
}
public MainWindowViewModel(IDateTimeService dateTimeService)
{
_dateTimeService = dateTimeService;
ButtonClickCommand = new DelegateCommand(OnButtonClick);
}
/// <summary>
/// Button Click Command Event
/// </summary>
private void OnButtonClick()
{
DateTimeString = _dateTimeService.GetDateTimeString();
}
}
}
실행 결과

확인 버튼 클릭 시 `DateTimeService`의 `GetDateTimeString`메서드가 호출되고, 현재 시간이 표시되는 것을 확인할 수 있다.
💡 예제 소스
https://github.com/elena-kim/wpf-study/tree/main/WpfStudy/DotNetDependencyInjection
'.NET > WPF' 카테고리의 다른 글
| [WPF] InvokeCommandAction 사용 시 바인딩 업데이트 타이밍 문제 (0) | 2024.11.26 |
|---|---|
| [WPF] 의존성 주입 예제 (2) - Prism.DryIoc 사용 (0) | 2024.11.24 |
| [WPF] 의존성 주입(Dependency Injection) (0) | 2024.11.15 |
| [WPF] 이벤트 라우팅, 버블링(Bubbling), 터널링(Tunneling) (1) | 2024.10.19 |
댓글