2022. 9. 1. 00:00ㆍMAUI
.NET MAUI 에서 view 와 view 간의 data 전달을 위해서 Messenger 를 이용한다.
MVVM 에서 특히 이 Messenger 를 이용한 Subscribe and Publish pattern 은 일반화된 데이터 전달 방식이다.
그런데 MAUI 에서도 Service 계층이 있을 수 있고 이 Service 계층은 view viewmodel 과는 다른 layer 에 있다고 생각해 보자. (다른 project 일 수도 있고 project 내에서 폴더로 구분하여 다른 폴더에 구현 했을수 도 있다.)
이럴경우는 CommunityToolkit.MVVM 에서 지원하는 Messager 는 사용하지 못할 수 있다.
이럴때를 이용하여 MediatR 이라는 것을 활용할 수 있다.
MediatR 은 Mediator 에 대한 dotnet 구현체 이다.
(과학자 분들이 MediatR은 mediator pattern 이 아니다라고 할텐데 .. 맞다 당신들 말이 전적으로 다 맞다)
어쨌든 이 MediatR 을 이용해 우리는 app 에서 viewmodel 과 다른 handler 또는 service 간에 data 를 전달 하겠다.
일단 MediatR Nuget 를 통해 설치 하자
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection
그런다음 MauiProgram.cs 로 이동하여 MediatR 을 Maui 에서 사용가능하도록 등록 하자!!
...
using MediatR;
...
...
builder.Services.AddMediatR(Assembly.GetExecutingAssembly());
...
일단 message 를 전달하기 위해 GetUserCommand 라는 Command 를 만들었다.
return 값이 있고 string 형태 이므로 IRequest<string> 형태를 Implements 한다.
Request/GetUserCommand.cs
using MediatR;
namespace MauiApp1.Request;
public class GetUserCommand : IRequest<string>
{
}
GetUserCommand 를 MediatR 에서 Send 하게 되면 IRequestHandler<GetUserCommand, string> 을 구현한 UserService 에서 처리하게 된다. 여기서는 httpClient 를 통해 mockaroo 라는 mock site 로 부터 json data 를 받고 있다.
Services/UserService.cs
using MauiApp1.Request;
using MediatR;
namespace MauiApp1.Services;
public class UserService : IRequestHandler<GetUserCommand, string>
{
public async Task<string> Handle(GetUserCommand request, CancellationToken cancellationToken)
{
using HttpClient httpClient = new HttpClient();
var response = await httpClient
.GetAsync("https://my.api.mockaroo.com/users.json?key=8d630ff0");
return await response.Content.ReadAsStringAsync();
}
}
public class User
{
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public string gender { get; set; }
public string ip_address { get; set; }
}
EventMechanism/MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp1.EventMechanism.MainPage"
xmlns:local="clr-namespace:MauiApp1.EventMechanism"
x:DataType="local:MainViewModel"
Title="MediatR Test">
<VerticalStackLayout>
<Label Text="{Binding Message, Mode=OneWay}"/>
<Button
Text="Change message"
Command="{Binding CallAPICommand}"/>
<CollectionView ItemsSource="{Binding UserModels}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:UserModel">
<Grid ColumnDefinitions="*,2*,2*,4*,*">
<Label Text="{Binding Id}" FontAttributes="Bold" />
<Label Grid.Column="1" Text="{Binding FirstName}" />
<Label Grid.Column="2" Text="{Binding LastName}" FontSize="12"/>
<Label Grid.Column="3" Text="{Binding Email}" FontSize="10"/>
<Label Grid.Column="4" Text="{Binding Gender}" FontSize="10"/>
<!--<Label Grid.Column="5" Text="{Binding IpAddress}" />-->
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ContentPage>
EventMechanism/MainPage.xaml.cs
using MauiApp1.InjectableServices;
namespace MauiApp1.EventMechanism;
public partial class MainPage : ContentPage, ITransientService
{
public MainPage(MainViewModel viewModel)
{
InitializeComponent();
BindingContext = viewModel;
}
}
viewModel에서는 IMediator 을 주입 받아서 CallApiCommand 가 실행되면 _mediator.send 를 통해 message 를 전달하고 Message 에는 UserService 로 부터 return 받는 string을 받게된다.
EventMechanism/MainViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MauiApp1.InjectableServices;
using MauiApp1.Request;
using MauiApp1.Services;
using MediatR;
using System.Collections.ObjectModel;
namespace MauiApp1.EventMechanism;
public partial class MainViewModel : ObservableObject, ITransientService
{
public MainViewModel(IMediator mediator)
{
UserModels ??= new ObservableCollection<UserModel>();
_mediator = mediator;
}
[ObservableProperty]
private int _counter;
[ObservableProperty]
private string _message;
private readonly IMediator _mediator;
[RelayCommand]
private void IncrementCounter() => Counter++;
[RelayCommand]
private async void CallAPI()
{
Message = await _mediator.Send(new GetUserCommand());
var users = System.Text.Json.JsonSerializer.Deserialize<List<User>>(Message);
foreach (var user in users)
{
UserModels.Add(new UserModel
{
id = user.id,
firstName = user.first_name,
lastName = user.last_name,
email = user.email,
gender = user.gender,
ipAddress = user.ip_address,
});
}
}
public ObservableCollection<UserModel> UserModels
{
get;
set;
}
}
public partial class UserModel : ObservableObject
{
[ObservableProperty]
public int id;
[ObservableProperty]
public string firstName;
[ObservableProperty]
public string lastName;
[ObservableProperty]
public string email;
[ObservableProperty]
public string gender;
[ObservableProperty]
public string ipAddress;
}
관련영상
'MAUI' 카테고리의 다른 글
.NET MAUI - Xunit 을 이용한 UnitTest (0) | 2022.09.02 |
---|---|
.NET MAUI - HttpClient 를 이용한 Rest Api 호출 (0) | 2022.08.31 |
.NET MAUI - Configuration 을 이용한 json 파일 제어 (0) | 2022.08.30 |
.NET MAUI - CommunityToolkit.Maui 유용한 Behavior 3 (0) | 2022.08.26 |
.NET MAUI - CommunityToolkit.Maui 유용한 Behavior 2 (0) | 2022.08.25 |