Skip to content

Instantly share code, notes, and snippets.

@relyky
Last active November 13, 2023 03:22
Show Gist options
  • Save relyky/f3405c3ec585c992e107cbacfc7d272e to your computer and use it in GitHub Desktop.
Save relyky/f3405c3ec585c992e107cbacfc7d272e to your computer and use it in GitHub Desktop.
C#, Catch and retry, CatchAndHandling, Aspect, AOP
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
}
}
}
}
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;
}
}
@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