Skip to content

Instantly share code, notes, and snippets.

@noxi515
Created February 21, 2018 11:04
Show Gist options
  • Save noxi515/2beaf8cab633fa49aea06c7eea287363 to your computer and use it in GitHub Desktop.
Save noxi515/2beaf8cab633fa49aea06c7eea287363 to your computer and use it in GitHub Desktop.
学生向け適当に書いてみたサンプル
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Prism.Ioc;
using Prism.Services;
public class SampleData
{
public string Prop0 { get; set; }
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
// 1. とりあえずそのまま書いちゃうパターン
// 見通し悪いしクラスの責務が混在するので最もよろしくない
// 検証する時とかしか書いちゃいけない
public class HogeViewModel_01
{
public async void OnInitialize()
{
var http = new HttpClient();
var response = await http.GetAsync("http://localhost/pop/team/epic");
response.EnsureSuccessStatusCode();
var result = JsonConvert.DeserializeObject<List<SampleData>>(await response.Content.ReadAsStringAsync());
// TODO なんかする
}
}
// 2. ちょっとクラス分けてみるパターン
public class SampleDataService_02
{
public async Task<List<SampleData>> GetAllAsync()
{
var http = new HttpClient();
var response = await http.GetAsync("http://localhost/pop/team/epic");
response.EnsureSuccessStatusCode();
return JsonConvert.DeserializeObject<List<SampleData>>(await response.Content.ReadAsStringAsync());
}
}
public class HogeViewModel_02
{
public async void OnInitialize()
{
var service = new SampleDataService_02();
var result = await service.GetAllAsync();
// TODO なんかする
}
}
// 3. ちょっとキャッシュしちゃうパターン
// シングルトンっていいよね
public class SampleDataService_03
{
public static SampleDataService_03 Instance { get; } = new SampleDataService_03();
private List<SampleData> Cache { get; set; }
private SampleDataService_03()
{
}
public async Task<List<SampleData>> GetAllAsync()
{
if (Cache != null)
{
return new List<SampleData>(Cache);
}
var http = new HttpClient();
var response = await http.GetAsync("http://localhost/pop/team/epic");
response.EnsureSuccessStatusCode();
return Cache = JsonConvert.DeserializeObject<List<SampleData>>(await response.Content.ReadAsStringAsync());
}
}
public class HogeViewModel_03
{
public async void OnInitialize()
{
var service = SampleDataService_03.Instance;
var result = await service.GetAllAsync();
// TODO なんかする
}
}
// 4. DIコンテナを利用するパターン
// DI = Dependency Injection
// 必要なオブジェクトの生成と管理をDIライブラリが受け持ってくれるので楽
// 大体はコンストラクタでオブジェクト生成時に受け取る
// 渡したサンプルはUnityというDIライブラリが組み込まれているので、ViewModel生成時にDIに登録されているオブジェクト受け取れる
// たとえば INavigationService もDIで受け取っているものの一つ
public class App_04
{
public void RegisterTypes(IContainerRegistry registry)
{
// オブジェクトの生成管理をして欲しいクラスを、管理方法を指定してDIコンテナに登録する
registry.RegisterSingleton<SampleDataService_04>();
}
}
public class SampleDataService_04
{
private List<SampleData> Cache { get; set; }
public async Task<List<SampleData>> GetAllAsync()
{
if (Cache != null)
{
return new List<SampleData>(Cache);
}
var http = new HttpClient();
var response = await http.GetAsync("http://localhost/pop/team/epic");
response.EnsureSuccessStatusCode();
return Cache = JsonConvert.DeserializeObject<List<SampleData>>(await response.Content.ReadAsStringAsync());
}
}
public class HogeViewModel_04
{
private SampleDataService_04 Service { get; }
public HogeViewModel_04(SampleDataService_04 service)
{
Service = service;
}
public async void OnInitialize()
{
var result = await Service.GetAllAsync();
// TODO なんかする
}
}
// 5. ちょっとエラー処理でもするパターン
// どんな方法が最も良いのかは長年の謎である
// むしろ俺が教えて欲しい
public class App_05
{
public void RegisterTypes(IContainerRegistry registry)
{
registry.RegisterSingleton<SampleDataService_05>();
registry.RegisterSingleton<ViewModelExceptionHandler>();
}
}
public class SampleDataService_05
{
private List<SampleData> Cache { get; set; }
public async Task<List<SampleData>> GetAllAsync()
{
if (Cache != null)
{
return new List<SampleData>(Cache);
}
var http = new HttpClient();
var response = await http.GetAsync("http://localhost/pop/team/epic");
response.EnsureSuccessStatusCode();
return Cache = JsonConvert.DeserializeObject<List<SampleData>>(await response.Content.ReadAsStringAsync());
}
}
public class HogeViewModel_05
{
private SampleDataService_05 Service { get; }
private ViewModelExceptionHandler ErrorHandler { get; }
public HogeViewModel_05(SampleDataService_05 service, ViewModelExceptionHandler errorHandler)
{
Service = service;
ErrorHandler = errorHandler;
}
public async void OnInitialize()
{
try
{
var result = await Service.GetAllAsync();
// TODO なんかする
}
catch (Exception e)
{
if (!await ErrorHandler.HandleHttpErrorAsync(e))
{
throw;
}
}
}
}
public class ViewModelExceptionHandler
{
private IPageDialogService DialogService { get; }
public ViewModelExceptionHandler(IPageDialogService dialogService)
{
DialogService = dialogService;
}
public async Task<bool> HandleHttpErrorAsync(Exception e)
{
if (e is TaskCanceledException)
{
// Timeout
await DialogService.DisplayAlertAsync("通信エラー", "サーバーへの接続がタイムアウトしました。クソ回線乙 ^_^", "OK");
return true;
}
if (e is HttpRequestException)
{
// サーバー側のエラー。EnsureSuccessStatusCodeでStatusCodeが200番台じゃ無いとここにくる
await DialogService.DisplayAlertAsync("通信エラー", "通信エラーが発生しました。ちょっと待ってリトライしてぴ-ぴーぴー。", "OK");
return true;
}
// HTTP系のエラーじゃないのでここでは何もしない
// NO MORE 握りつぶし
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment