mirror of
https://gitee.com/LongbowEnterprise/BootstrapBlazor.git
synced 2024-11-30 02:58:37 +08:00
!1754 feat(#I4720Q): add location services
* chore: bump version to 5.7.4 * doc: 增加自定义扩展文档 * doc: 增加 Locator 菜单 * refactor: 调整 IPLocatorOption 内部参数 * refactor: 移除 IPLocator 服务注入更改到 BootstrapBlazor * refactor: 日志增加 IP 地址 * chore: 移动文件 * doc: 增加编码注意事项 * feat: 增加本地连接解析 * feat: 根据最新百度接口更新类结构 * chore: 增加编码支持 * doc: 增加 Locator 示例 * feat: 增加 Locator 配置回调委托 * refactor: 重构代码消除提示信息 * chore: 增加 Http 包依赖 * feat: 增加接口实现类 * feat: 增加 IPLocator 服务注入 * feat: 增加 AddIPLocator 服务注入代码 * feat: 增加 StringExtensions 扩展方法 * feat: 增加 IPLocator 相关接口定义 * refactor: 更改日志 Key 值
This commit is contained in:
parent
2cfd040561
commit
2b7112653c
@ -3,18 +3,10 @@
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace BootstrapBlazor.Server
|
||||
{
|
||||
@ -52,7 +44,8 @@ namespace BootstrapBlazor.Server
|
||||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddLogging(builder => builder.AddConsole());
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
|
||||
services.AddCors();
|
||||
services.AddResponseCompression();
|
||||
|
||||
|
@ -379,6 +379,7 @@
|
||||
"GroupBox": "GroupBox",
|
||||
"HandwrittenPage": "HandwrittenPage",
|
||||
"ListView": "ListView",
|
||||
"Locator": "Locator",
|
||||
"Popover": "Popover",
|
||||
"QRCode": "QRCode",
|
||||
"Search": "Search",
|
||||
|
@ -379,6 +379,7 @@
|
||||
"GroupBox": "集合 GroupBox",
|
||||
"HandwrittenPage": "手写组件 HandwrittenPage",
|
||||
"ListView": "列表组件 ListView",
|
||||
"Locator": "位置定位 Locator",
|
||||
"Popover": "弹出窗 Popover",
|
||||
"QRCode": "二维码 QRCode",
|
||||
"Search": "搜索框 Search",
|
||||
|
@ -14,9 +14,6 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// </summary>
|
||||
public partial class Client
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private WebClientService? ClientService { get; set; }
|
||||
|
58
src/BootstrapBlazor.Shared/Pages/Samples/Locator.razor
Normal file
58
src/BootstrapBlazor.Shared/Pages/Samples/Locator.razor
Normal file
@ -0,0 +1,58 @@
|
||||
@page "/locator"
|
||||
|
||||
<h3>获取 IP 地理位置</h3>
|
||||
|
||||
<h4>多用系统日志跟踪</h4>
|
||||
|
||||
<Block Title="普通用法" Introduction="注入服务显示客户端地理位置信息">
|
||||
<p><b>用法介绍</b></p>
|
||||
<div class="mb-3">
|
||||
<p>组件中使用注入服务 <code>IIPLocatorProvider</code> 调用 <code>Locate</code> 方法</p>
|
||||
<Pre>[Inject]
|
||||
[NotNull]
|
||||
private IIPLocatorProvider? IPLocator { get; set; }
|
||||
</Pre>
|
||||
</div>
|
||||
<Tips>
|
||||
<div>由于地理位置查询接口返回字符集可能是其他字符集如 <code>gbk</code>,程序会报错;</div>
|
||||
<div><b>解决办法:</b></div>
|
||||
<div><code>Startup</code> 文件中 <code>ConfigureServices</code> 方法内增加下面这句话即可解决</div>
|
||||
</Tips>
|
||||
<Pre>Encoding.RegisterProvider(CodePagesEncodingProvider.Instance)</Pre>
|
||||
<div class="mb-2">IP 测试数据</div>
|
||||
<div><code>112.224.74.239</code> 山东省济南市 联通</div>
|
||||
<div class="mb-3"><code>183.160.236.53</code> 安徽省合肥市 电信</div>
|
||||
<div class="row g-3 form-inline">
|
||||
<div class="col-12 col-sm-6">
|
||||
<BootstrapInput @bind-Value="Ip" DisplayText="Ip 地址" ShowLabel="true" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<Display Value="Location" DisplayText="地理位置" ShowLabel="true" />
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<Button Icon="fa fa-location" Text="定位" OnClick="OnClick" />
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3"><b>扩展自定义地理位置查询接口</b></p>
|
||||
<div>
|
||||
<p><b>1. 实现自定义定位器</b></p>
|
||||
<Pre>private class CustomerLocator : IIPLocator
|
||||
{
|
||||
public Task<string> Locate(IPLocatorOption option)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}</Pre>
|
||||
<p><b>2. 配置自定义定位器</b></p>
|
||||
<Pre>public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddBootstrapBlazor(locatorAction: option =>
|
||||
{
|
||||
option.LocatorName = "CustomerLocator";
|
||||
option.LocatorFactory = name => new CustomerLocator();
|
||||
option.Url = "http://apis.juhe.cn/ip/ipNew?key=f57102d1b9fadd3f4a1c29072d0c0206&ip=";
|
||||
});
|
||||
}</Pre>
|
||||
<div>通过 <code>AddBootstrapBlazor</code> 方法的回调委托参数进行自定义定位器 <code>CustomerLocator</code> 配置</div>
|
||||
</div>
|
||||
</Block>
|
54
src/BootstrapBlazor.Shared/Pages/Samples/Locator.razor.cs
Normal file
54
src/BootstrapBlazor.Shared/Pages/Samples/Locator.razor.cs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public partial class Locator
|
||||
{
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private WebClientService? ClientService { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IIPLocatorProvider? IPLocator { get; set; }
|
||||
|
||||
private string? Ip { get; set; }
|
||||
|
||||
private string? Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
/// <returns></returns>
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
if (firstRender)
|
||||
{
|
||||
await ClientService.RetrieveRemoteInfo();
|
||||
Ip = ClientService.Ip;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnClick()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Ip))
|
||||
{
|
||||
Location = await IPLocator.Locate(Ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -435,6 +435,12 @@ namespace BootstrapBlazor.Shared.Shared
|
||||
Url = "listviews"
|
||||
},
|
||||
new()
|
||||
{
|
||||
IsNew = true,
|
||||
Text = Localizer["Locator"],
|
||||
Url = "locator"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Text = Localizer["QRCode"],
|
||||
Url = "qrcodes"
|
||||
|
@ -1,13 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>5.7.3</Version>
|
||||
<Version>5.7.4</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="5.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="5.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0" />
|
||||
</ItemGroup>
|
||||
@ -16,6 +17,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.0-preview.7.*" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="6.0.0-preview.7.*" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0-preview.7.*" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-preview.7.*" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.0-preview.7.*" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.0-preview.7.*" />
|
||||
</ItemGroup>
|
||||
|
53
src/BootstrapBlazor/Components/IPLocator/BaiDuIPLocator.cs
Normal file
53
src/BootstrapBlazor/Components/IPLocator/BaiDuIPLocator.cs
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
internal class BaiDuIPLocator : DefaultIPLocator
|
||||
{
|
||||
/// <summary>
|
||||
/// 详细地址信息
|
||||
/// </summary>
|
||||
public IEnumerable<LocationInfo>? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结果状态返回码
|
||||
/// </summary>
|
||||
public string? Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="option"></param>
|
||||
/// <returns></returns>
|
||||
public override Task<string> Locate(IPLocatorOption option) => Locate<BaiDuIPLocator>(option);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Status == "0" ? (Data?.FirstOrDefault()?.Location ?? "XX XX") : "Error";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class LocationInfo
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Location { get; set; }
|
||||
}
|
||||
}
|
50
src/BootstrapBlazor/Components/IPLocator/DefaultIPLocator.cs
Normal file
50
src/BootstrapBlazor/Components/IPLocator/DefaultIPLocator.cs
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Net.Http.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
internal class DefaultIPLocator : IIPLocator
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="option"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<string> Locate(IPLocatorOption option) => Task.FromResult(string.Empty);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="option"></param>
|
||||
/// <returns></returns>
|
||||
protected static async Task<string> Locate<T>(IPLocatorOption option) where T : class
|
||||
{
|
||||
string? ret = null;
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(option.Url) && !string.IsNullOrEmpty(option.IP) && option.HttpClient != null)
|
||||
{
|
||||
var url = string.Format(option.Url, option.IP);
|
||||
using var token = new CancellationTokenSource(option.RequestTimeout);
|
||||
var result = await option.HttpClient.GetFromJsonAsync<T>(url, token.Token);
|
||||
ret = result?.ToString();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
option.Logger?.LogError(ex, option.Url, option.IP);
|
||||
}
|
||||
return ret ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认 IP 地理位置定位器
|
||||
/// </summary>
|
||||
internal class DefaultIPLocatorProvider : IIPLocatorProvider
|
||||
{
|
||||
private readonly IPLocatorOption _option = new();
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
/// <param name="logger"></param>
|
||||
public DefaultIPLocatorProvider(IHttpClientFactory factory, ILogger<DefaultIPLocatorProvider> logger)
|
||||
{
|
||||
_option.HttpClient = factory.CreateClient();
|
||||
_option.Logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定位方法
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> Locate(string ip)
|
||||
{
|
||||
string? ret = null;
|
||||
|
||||
// 解析本机地址
|
||||
if (string.IsNullOrEmpty(ip) || _option.Localhosts.Any(p => p == ip))
|
||||
{
|
||||
ret = "本地连接";
|
||||
}
|
||||
else
|
||||
{
|
||||
// IP定向器地址未设置
|
||||
_option.IP = ip;
|
||||
if (string.IsNullOrEmpty(_option.Url))
|
||||
{
|
||||
ret = string.Empty;
|
||||
}
|
||||
var locator = _option.LocatorFactory(_option.LocatorName);
|
||||
ret = await locator.Locate(_option);
|
||||
}
|
||||
return ret ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
21
src/BootstrapBlazor/Components/IPLocator/IIPLocator.cs
Normal file
21
src/BootstrapBlazor/Components/IPLocator/IIPLocator.cs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface IIPLocator
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="option">定位器配置信息</param>
|
||||
/// <returns>定位器定位结果</returns>
|
||||
Task<string> Locate(IPLocatorOption option);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// IP 地址定位服务
|
||||
/// </summary>
|
||||
public interface IIPLocatorProvider
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
Task<string> Locate(string ip);
|
||||
}
|
||||
}
|
54
src/BootstrapBlazor/Components/IPLocator/IPLocatorOption.cs
Normal file
54
src/BootstrapBlazor/Components/IPLocator/IPLocatorOption.cs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BootstrapBlazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// IP定位器配置项
|
||||
/// </summary>
|
||||
public class IPLocatorOption
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 定位器名称
|
||||
/// </summary>
|
||||
public string LocatorName { get; set; } = nameof(BaiDuIPLocator);
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 定位器创建方法未设置使用内部定位器
|
||||
/// </summary>
|
||||
public Func<string, IIPLocator> LocatorFactory { get; set; } = _ => new BaiDuIPLocator();
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 IP定位器请求地址
|
||||
/// </summary>
|
||||
public string Url { get; set; } = "https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?resource_id=6006&query={0}";
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 IP地址请求超时时间 默认为 3000 毫秒
|
||||
/// </summary>
|
||||
public int RequestTimeout { get; set; } = 3000;
|
||||
|
||||
/// <summary>
|
||||
/// 获得 本机地址列表
|
||||
/// </summary>
|
||||
public List<string> Localhosts { get; } = new List<string>(new string[] { "::1", "127.0.0.1" });
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 IP地址
|
||||
/// </summary>
|
||||
internal string? IP { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 HttpClient 实体类
|
||||
/// </summary>
|
||||
internal HttpClient? HttpClient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 ILogger 实体类
|
||||
/// </summary>
|
||||
internal ILogger<IIPLocatorProvider>? Logger { get; set; }
|
||||
}
|
||||
}
|
@ -88,7 +88,7 @@ namespace BootstrapBlazor.Components
|
||||
logger.AppendLine();
|
||||
}
|
||||
|
||||
logger.AppendFormat("{0}: {1}", "Exception:", exception.Message);
|
||||
logger.AppendFormat("{0}: {1}", "Exception", exception.Message);
|
||||
logger.AppendLine();
|
||||
|
||||
logger.Append(new string('*', 45));
|
||||
|
@ -24,12 +24,13 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="configureOptions"></param>
|
||||
/// <param name="setupAction"></param>
|
||||
/// <param name="localizationAction"></param>
|
||||
/// <param name="locatorAction"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddBootstrapBlazor(this IServiceCollection services, Action<BootstrapBlazorOptions>? configureOptions = null, Action<JsonLocalizationOptions>? setupAction = null)
|
||||
public static IServiceCollection AddBootstrapBlazor(this IServiceCollection services, Action<BootstrapBlazorOptions>? configureOptions = null, Action<JsonLocalizationOptions>? localizationAction = null, Action<IPLocatorOption>? locatorAction = null)
|
||||
{
|
||||
services.AddAuthorizationCore();
|
||||
services.AddJsonLocalization(setupAction);
|
||||
services.AddJsonLocalization(localizationAction);
|
||||
services.TryAddScoped<IComponentIdGenerator, DefaultIdGenerator>();
|
||||
services.TryAddScoped<ITableExcelExport, DefaultExcelExport>();
|
||||
services.TryAddScoped(typeof(IDataService<>), typeof(NullDataService<>));
|
||||
@ -47,6 +48,13 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
configureOptions?.Invoke(options);
|
||||
});
|
||||
|
||||
services.AddHttpClient();
|
||||
services.TryAddSingleton<IIPLocatorProvider, DefaultIPLocatorProvider>();
|
||||
services.Configure<IPLocatorOption>(options =>
|
||||
{
|
||||
locatorAction?.Invoke(options);
|
||||
});
|
||||
return services;
|
||||
}
|
||||
|
||||
|
100
src/BootstrapBlazor/Extensions/StringExtensions.cs
Normal file
100
src/BootstrapBlazor/Extensions/StringExtensions.cs
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BootstrapBlazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
internal static class StringExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// SpanSplit 扩展方法
|
||||
/// </summary>
|
||||
/// <param name="source">源数组</param>
|
||||
/// <param name="splitStr">分隔符数组 分割规则作为整体</param>
|
||||
/// <param name="stringSplitOptions">StringSplitOptions 选项</param>
|
||||
/// <returns>分割后的字符串数组</returns>
|
||||
public static List<string> SpanSplit(this string source, string? splitStr = null, StringSplitOptions stringSplitOptions = StringSplitOptions.None)
|
||||
{
|
||||
var ret = new List<string>();
|
||||
if (string.IsNullOrEmpty(source))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(splitStr))
|
||||
{
|
||||
splitStr = Environment.NewLine;
|
||||
}
|
||||
|
||||
var sourceSpan = source.AsSpan();
|
||||
var splitSpan = splitStr.AsSpan();
|
||||
|
||||
do
|
||||
{
|
||||
var n = sourceSpan.IndexOf(splitSpan);
|
||||
if (n == -1)
|
||||
{
|
||||
n = sourceSpan.Length;
|
||||
}
|
||||
|
||||
ret.Add(stringSplitOptions == StringSplitOptions.None
|
||||
? sourceSpan.Slice(0, n).ToString()
|
||||
: sourceSpan.Slice(0, n).Trim().ToString());
|
||||
sourceSpan = sourceSpan[Math.Min(sourceSpan.Length, n + splitSpan.Length)..];
|
||||
}
|
||||
while (sourceSpan.Length > 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SpanSplit 扩展方法
|
||||
/// </summary>
|
||||
/// <param name="source">源数组</param>
|
||||
/// <param name="splitStr">分隔符数组 分割规则是任意一个</param>
|
||||
/// <param name="stringSplitOptions">StringSplitOptions 选项</param>
|
||||
/// <returns>分割后的字符串数组</returns>
|
||||
public static List<string> SpanSplitAny(this string source, string splitStr, StringSplitOptions stringSplitOptions = StringSplitOptions.None)
|
||||
{
|
||||
var ret = new List<string>();
|
||||
if (string.IsNullOrEmpty(source))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(splitStr))
|
||||
{
|
||||
ret.Add(source);
|
||||
return ret;
|
||||
}
|
||||
|
||||
var sourceSpan = source.AsSpan();
|
||||
var splitSpan = splitStr.AsSpan();
|
||||
|
||||
do
|
||||
{
|
||||
var n = sourceSpan.IndexOfAny(splitSpan);
|
||||
if (n == -1)
|
||||
{
|
||||
n = sourceSpan.Length;
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
ret.Add(stringSplitOptions == StringSplitOptions.None
|
||||
? sourceSpan.Slice(0, n).ToString()
|
||||
: sourceSpan.Slice(0, n).Trim().ToString());
|
||||
}
|
||||
|
||||
sourceSpan = sourceSpan[Math.Min(sourceSpan.Length, n + 1)..];
|
||||
}
|
||||
while (sourceSpan.Length > 0);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user