Last active
November 13, 2023 03:22
-
-
Save relyky/f3405c3ec585c992e107cbacfc7d272e to your computer and use it in GitHub Desktop.
C#, Catch and retry, CatchAndHandling, Aspect, AOP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| class Program | |
| { | |
| static void Main(string[] args) | |
| { | |
| CatchAndRetry<ApplicationException>(2, 3000, n => | |
| { | |
| Console.WriteLine($"AAA{n}"); | |
| if (n > 1) | |
| throw new ApplicationException("Fail!"); | |
| Console.WriteLine($"Success{n}"); | |
| }); | |
| CatchAndRetry<ApplicationException>(new int[] { 1000, 2000, 3000 }, n => | |
| { | |
| Console.WriteLine($"AAA{n}"); | |
| if(n < 2) | |
| throw new ApplicationException("Fail!"); | |
| Console.WriteLine($"Success{n}"); | |
| }); | |
| Console.WriteLine("Press any key to continue."); | |
| Console.ReadKey(); | |
| } | |
| static void CatchAndRetry<TException>(int retryCount, int retryDuration, Action<int> act) | |
| where TException : Exception | |
| { | |
| for (; ; ) | |
| { | |
| try | |
| { | |
| act.Invoke(retryCount); | |
| break; | |
| } | |
| catch (TException) | |
| { | |
| if (retryCount-- > 0) // decide to retry or not. | |
| { | |
| // waiting short time and then re-exec. | |
| System.Threading.SpinWait.SpinUntil(() => false, retryDuration); | |
| continue; // retry | |
| } | |
| throw; // fail & leave | |
| } | |
| } | |
| } | |
| static void CatchAndRetry<TException>(int[] retryDuration, Action<int> act) | |
| where TException : Exception | |
| { | |
| int idx = 0; | |
| for (; ; ) | |
| { | |
| try | |
| { | |
| act.Invoke(idx); | |
| break; | |
| } | |
| catch (TException) | |
| { | |
| if (retryDuration.Length > idx) // decide to retry or not. | |
| { | |
| // waiting short time and then re-exec. | |
| System.Threading.SpinWait.SpinUntil(() => false, retryDuration[idx++]); | |
| continue; // retry | |
| } | |
| throw; // fail & leave | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Task HandleQuery() => CatchHandling(async () => | |
| { | |
| var qryArgs = new TodoQryAgs | |
| { | |
| Msg = f_testFail ? "測試邏輯失敗" : "今天天氣真好", | |
| Amt = 999 | |
| }; | |
| dataList = await bizApi.QryDataListAsync(qryArgs); | |
| }); | |
| Task HandleAdd() => CatchHandling(async () => | |
| { | |
| var newTodo = await bizApi.AddFormDataAsync(newTodoDesc); | |
| // Success | |
| dataList.Add(newTodo); | |
| newTodoDesc = string.Empty; | |
| }); | |
| //---------------------------------------------------------------------- | |
| //# AOP with Decorator | |
| async Task CatchHandling(Func<Task> action) | |
| { | |
| try | |
| { | |
| f_loading = true; | |
| errMsg = string.Empty; | |
| await action(); | |
| } | |
| catch (ApiException ex) | |
| { | |
| if (ex.StatusCode == HttpStatusCode.BadRequest) | |
| { | |
| var msg = await ex.GetContentAsAsync<ErrMsg>(); | |
| errMsg = $"ApiException: {msg.Severity}-{msg.Message}"; | |
| } | |
| else | |
| { | |
| errMsg = $"ApiException: {ex.Message}"; | |
| } | |
| } | |
| catch (Exception ex) | |
| { | |
| errMsg = "EXCEPTION: " + ex.Message; | |
| } | |
| finally | |
| { | |
| f_loading = false; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @page "/FooPage" | |
| @attribute [Authorize] | |
| @inject IDialogServiceEx dlgSvc | |
| @inject ILogger<_SSO1010> logger | |
| @inject FooBiz bizSvc | |
| <MudContainer> | |
| <FooForm ...> | |
| </MudContainer> | |
| @code { | |
| //## State | |
| List<FooItemInfo> dataList = new(); | |
| bool f_loading = false; | |
| protected override Task OnInitializedAsync() => CatchHandling(async () => | |
| { | |
| dataList = await Task.Run(() => bizSvc.QryDataList()); | |
| }); | |
| Task HandleAdd(FooItemInfo item) => CatchHandling(async () => | |
| { | |
| //# 資料演算 | |
| (item, string message) = await Task.Run(() => bizSvc.AddFormData(item)); | |
| if (message != "SUCCESS") | |
| { | |
| dlgSvc.ShowAlert(message); | |
| return; | |
| } | |
| // UI | |
| dataList.Add(item); | |
| dataList = dataList.OrderBy(c => c.OrderBy).ToList(); | |
| }); | |
| Task HandleUpdate(FooItemInfo item) => CatchHandling(async () => | |
| { | |
| //# 資料演算 | |
| (item, string message) = await Task.Run(() => bizSvc.UpdFormData(item)); | |
| if (message != "SUCCESS") | |
| { | |
| await dlgSvc.ConfirmAsync(message, "更新失敗請重新確認!"); | |
| await refDataGrid.SetEditingItemAsync(item); | |
| return; | |
| } | |
| // UI | |
| dataList = dataList.OrderBy(c => c.OrderBy).ToList(); | |
| }); | |
| Task HandleRemove(FooItemInfo item) => CatchHandling(async () => | |
| { | |
| //# 再確定一次 | |
| bool isConfirm = await dlgSvc.ConfirmAsync($"再確定一次要刪除這筆資料?"); | |
| if (!isConfirm) return; | |
| //# 資料演算 | |
| await Task.Run(() => bizSvc.DelFormData(item)); | |
| //# 成功後同步UI資料 & 刷新畫面 | |
| dataList.Remove(item); | |
| dlgSvc.ShowAlert("刪除完成。", type: Severity.Success); | |
| }); | |
| //# AOP with Decorator ------------------------------------------------ | |
| async Task CatchHandling(Func<Task> action) | |
| { | |
| try | |
| { | |
| f_loading = true; | |
| await InvokeAsync(StateHasChanged); | |
| await action(); | |
| } | |
| catch (Exception ex) | |
| { | |
| logger.LogError(ex, "出現例外!" + ex.Message); | |
| dlgSvc.ShowAlert(ex.Message, "出現例外!"); | |
| } | |
| finally | |
| { | |
| f_loading = false; | |
| await InvokeAsync(StateHasChanged); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment