如何使路由器根据用户所在的国家/地区从不同的程序集中加载页面
How to make the Router load a page from a different assembly based on the country the user is in
我有一个应用程序,我想将其设置为特定国家/地区,以便针对相同的路线根据国家/地区显示不同的页面。
对于每个国家/地区,我都有一个延迟加载的 RCL,其中包含自定义组件。我的目标是当我转到 domain.com/
或 domain.com/shop
时,特定国家/地区的组件将从 Razor Class 库加载。这意味着多个组件在 RCL 之间具有相同的路由。
举个例子:
- 美国:路由器将从
USApp.dll
加载 domain.com/shop
。
- 加拿大:路由器将从
CanadaApp.dll
加载 domain.com/shop
。
国家/地区存储在浏览器的本地存储中,可以随时更改。
我可以通过哪些方式实现这一目标?没有关于这种情况的自定义路由的文档。
事实证明解决方案非常简单。正如@MisterMagoo 所指出的,您可以即时更改其他程序集。
这就是我最终得到的结果:
App.razor
:
@using System.Reflection
@using Blazored.LocalStorage
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject LazyAssemblyLoader AssemblyLoader
@inject ILogger<App> Logger
@inject ILocalStorageService localStorageService
<CascadingValue Value="AppCountry">
<CascadingAuthenticationState>
<Router AdditionalAssemblies="@lazyLoadedAssemblies" AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true" OnNavigateAsync="@OnNavigateAsync">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
@if (!context.User.Identity.IsAuthenticated)
{
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
</CascadingValue>
App.razor.cs
:
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Client
{
public partial class App : ComponentBase
{
private List<Assembly> lazyLoadedAssemblies = new();
public string AppCountry { get; set; }
private async Task OnNavigateAsync(NavigationContext args)
{
try
{
AppCountry = await localStorageService.GetItemAsync<string>("Country");
Console.WriteLine(AppCountry);
if (string.IsNullOrEmpty(AppCountry))
{
AppCountry = "RO";
}
IEnumerable<Assembly> assemblies = Enumerable.Empty<Assembly>();
switch (await localStorageService.GetItemAsync<string>("Country"))
{
case "RO":
assemblies = await AssemblyLoader.LoadAssembliesAsync(
new[]
{
"RomanianAppLayout.dll"
});
break;
case "US":
assemblies = await AssemblyLoader.LoadAssembliesAsync(
new[]
{
"USAppLayout.dll"
});
break;
default:
await localStorageService.SetItemAsync("Country", "RO");
goto case "RO";
}
lazyLoadedAssemblies.Clear();
lazyLoadedAssemblies.AddRange(assemblies);
}
catch (Exception ex)
{
Logger.LogError("Error: {Message}", ex.Message);
}
}
}
}
我有一个应用程序,我想将其设置为特定国家/地区,以便针对相同的路线根据国家/地区显示不同的页面。
对于每个国家/地区,我都有一个延迟加载的 RCL,其中包含自定义组件。我的目标是当我转到 domain.com/
或 domain.com/shop
时,特定国家/地区的组件将从 Razor Class 库加载。这意味着多个组件在 RCL 之间具有相同的路由。
举个例子:
- 美国:路由器将从
USApp.dll
加载domain.com/shop
。 - 加拿大:路由器将从
CanadaApp.dll
加载domain.com/shop
。
国家/地区存储在浏览器的本地存储中,可以随时更改。
我可以通过哪些方式实现这一目标?没有关于这种情况的自定义路由的文档。
事实证明解决方案非常简单。正如@MisterMagoo 所指出的,您可以即时更改其他程序集。
这就是我最终得到的结果:
App.razor
:
@using System.Reflection
@using Blazored.LocalStorage
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject LazyAssemblyLoader AssemblyLoader
@inject ILogger<App> Logger
@inject ILocalStorageService localStorageService
<CascadingValue Value="AppCountry">
<CascadingAuthenticationState>
<Router AdditionalAssemblies="@lazyLoadedAssemblies" AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true" OnNavigateAsync="@OnNavigateAsync">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
@if (!context.User.Identity.IsAuthenticated)
{
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
</CascadingValue>
App.razor.cs
:
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Client
{
public partial class App : ComponentBase
{
private List<Assembly> lazyLoadedAssemblies = new();
public string AppCountry { get; set; }
private async Task OnNavigateAsync(NavigationContext args)
{
try
{
AppCountry = await localStorageService.GetItemAsync<string>("Country");
Console.WriteLine(AppCountry);
if (string.IsNullOrEmpty(AppCountry))
{
AppCountry = "RO";
}
IEnumerable<Assembly> assemblies = Enumerable.Empty<Assembly>();
switch (await localStorageService.GetItemAsync<string>("Country"))
{
case "RO":
assemblies = await AssemblyLoader.LoadAssembliesAsync(
new[]
{
"RomanianAppLayout.dll"
});
break;
case "US":
assemblies = await AssemblyLoader.LoadAssembliesAsync(
new[]
{
"USAppLayout.dll"
});
break;
default:
await localStorageService.SetItemAsync("Country", "RO");
goto case "RO";
}
lazyLoadedAssemblies.Clear();
lazyLoadedAssemblies.AddRange(assemblies);
}
catch (Exception ex)
{
Logger.LogError("Error: {Message}", ex.Message);
}
}
}
}