昨天講了中介層的觀念,今天我們來實作中介層!
中介層通常會以一個類別封裝起來,再由擴充方法曝露。假設現在有個需求,要透過 URL 中一個區塊來決定語系。範例程式碼可以參考這邊。
URL | 語系 |
---|---|
/ | zh-TW |
/en-us/ | en-US |
/de-de/ | de-DE |
直接將中介層邏輯寫在 Startup.Configure
方法中:
public class Startup
{
private static readonly string[] EnabledCultures = new[] {"zh-tw", "en-us", "de-de"};
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Use((context, next) =>
{
var path = context.Request.Path;
var match = Regex.Match(path, $"^/({string.Join('|', EnabledCultures)})/CultureMiddleware");
var defaultCulture = "zh-tw";
if (match.Success)
{
defaultCulture = match.Groups[1].Value;
context.Request.Path = new PathString("/CultureMiddleware/Index");
}
var culture = new CultureInfo(defaultCulture);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
// Call the next delegate/middleware in the pipeline
return next();
});
app.Run(async context =>
{
await context.Response.WriteAsync(
$"你的語系是:{CultureInfo.CurrentCulture.DisplayName}",
Encoding.UTF8);
});
}
}
這個範例中,EnabledCultures
變數定義應用程式中支援的語系。
private static readonly string[] EnabledCultures = new[] {"zh-tw", "en-us", "de-de"};
利用正規表示式來搜尋 URL 中的語系區塊,如果找不到會預設為 zh-tw
。同時把要求的路徑指定為 /CultureMiddleware/Index,否則 router 會認錯 Controller。
var match = Regex.Match(path, $"/({string.Join('|', EnabledCultures)})");
var defaultCulture = "zh-tw";
if (match.Success)
{
defaultCulture = match.Groups[1].Value;
context.Request.Path = new PathString("/CultureMiddleware/Index");
}
最後設定應用程式中的語系。
var culture = new CultureInfo(defaultCulture);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
不同 URL 顯示的結果:
一般習慣會把中介層的邏輯封裝成一個類別,範例程式碼可以參考這邊。
把委任封裝成類別:
public class RequestCultureMiddleware
{
private static readonly string[] EnabledCultures = new[] { "zh-tw", "en-us", "de-de" };
private readonly RequestDelegate _next;
public RequestCultureMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var path = context.Request.Path;
var match = Regex.Match(path, $"/({string.Join('|', EnabledCultures)})");
var defaultCulture = "zh-tw";
if (match.Success)
{
defaultCulture = match.Groups[1].Value;
context.Request.Path = new PathString("/CultureMiddleware/Index");
}
var culture = new CultureInfo(defaultCulture);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
// Call the next delegate/middleware in the pipeline
await _next(context);
}
}
透過 IApplicationBuilder
曝露中介層:
public static class RequestCultureMiddlewareExtensions
{
public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCultureMiddleware>();
}
}
在 Startup.Configure
中設定中介層:
public void Configure(IApplicationBuilder app)
{
app.UseRequestCulture();
app.Run(async context =>
{
await context.Response.WriteAsync(
$"你的語系是:{CultureInfo.CurrentCulture.DisplayName}",
Encoding.UTF8);
});
}