committed by
GitHub
296 changed files with 4095 additions and 3431 deletions
@ -1,10 +1,10 @@ |
|||
using Volo.Abp.EventBus; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace CompanyName.ProjectName.CAP |
|||
namespace Lion.Abp.Cap |
|||
{ |
|||
[DependsOn(typeof(AbpEventBusModule))] |
|||
public class AbpCapModule : AbpModule |
|||
public class LionAbpCapModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
@ -1,12 +1,13 @@ |
|||
using Nest; |
|||
using Volo.Abp.Domain.Services; |
|||
|
|||
namespace CompanyName.ProjectName.QueryManagement.ElasticSearch |
|||
namespace Lion.Abp.ElasticSearch |
|||
{ |
|||
public abstract class ElasticsearchBasicRepository : DomainService |
|||
{ |
|||
private readonly IElasticsearchProvider _elasticsearchProvider; |
|||
|
|||
// ReSharper disable once PublicConstructorInAbstractClass
|
|||
public ElasticsearchBasicRepository(IElasticsearchProvider elasticsearchProvider) |
|||
{ |
|||
_elasticsearchProvider = elasticsearchProvider; |
|||
@ -1,8 +1,7 @@ |
|||
using System; |
|||
using Nest; |
|||
using Nest; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace CompanyName.ProjectName.QueryManagement.ElasticSearch |
|||
namespace Lion.Abp.ElasticSearch |
|||
{ |
|||
public interface IElasticsearchProvider : ISingletonDependency |
|||
{ |
|||
@ -0,0 +1,10 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net5.0</TargetFramework> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<PackageReference Include="NEST" Version="7.14.1" /> |
|||
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="4.4.0" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -0,0 +1,9 @@ |
|||
using System; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Lion.Abp.ElasticSearch |
|||
{ |
|||
public class LionAbpElasticSearchModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Lion.Abp.Extension |
|||
{ |
|||
[Serializable] |
|||
public class CustomeListResultDto<T> |
|||
{ |
|||
public IReadOnlyList<T> Items |
|||
{ |
|||
get { return _items ??= new List<T>(); } |
|||
set => _items = value; |
|||
} |
|||
|
|||
private IReadOnlyList<T> _items; |
|||
|
|||
public CustomeListResultDto() |
|||
{ |
|||
} |
|||
|
|||
public CustomeListResultDto(IReadOnlyList<T> items) |
|||
{ |
|||
Items = items; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Lion.Abp.Extension |
|||
{ |
|||
[Serializable] |
|||
public class CustomePagedResultDto<T> : CustomeListResultDto<T> |
|||
{ |
|||
public long TotalCount { get; set; } |
|||
|
|||
public CustomePagedResultDto() |
|||
{ |
|||
} |
|||
|
|||
public CustomePagedResultDto(long totalCount, IReadOnlyList<T> items) |
|||
: base(items) |
|||
{ |
|||
TotalCount = totalCount; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
namespace Lion.Abp.Extension |
|||
{ |
|||
|
|||
|
|||
public abstract class FromSelectorBase |
|||
{ |
|||
protected FromSelectorBase(int value, string label) |
|||
{ |
|||
Value = value; |
|||
Label = label; |
|||
} |
|||
public int Value { get; protected set; } |
|||
public string Label { get; protected set; } |
|||
} |
|||
|
|||
public abstract class FromSelectorBase<TValue, TLabel> |
|||
{ |
|||
protected FromSelectorBase(TValue value, TLabel label) |
|||
{ |
|||
Value = value; |
|||
Label = label; |
|||
} |
|||
|
|||
public TValue Value { get; protected set; } |
|||
public TLabel Label { get; protected set; } |
|||
} |
|||
|
|||
public class FromSelector : FromSelectorBase |
|||
{ |
|||
public FromSelector(int value, string label) : base(value, label) |
|||
{ |
|||
} |
|||
} |
|||
|
|||
public class FromSelector<TValue, TLabel> : FromSelectorBase<TValue, TLabel> |
|||
{ |
|||
public FromSelector(TValue value, TLabel label) : base(value, label) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System; |
|||
|
|||
namespace Lion.Abp.Extension |
|||
{ |
|||
public class IdInput |
|||
{ |
|||
public Guid Id { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Lion.Abp.Extension |
|||
{ |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 分页查询时使用的Dto类型
|
|||
/// </summary>
|
|||
public class PagingBase : IValidatableObject |
|||
{ |
|||
public const int MaxPageSize = 100000; |
|||
|
|||
/// <summary>
|
|||
/// 当前页面.默认从1开始
|
|||
/// </summary>
|
|||
public int PageIndex { get; set; } = 1; |
|||
|
|||
/// <summary>
|
|||
/// 每页多少条.每页显示多少记录
|
|||
/// </summary>
|
|||
public int PageSize { get; set; } = 10; |
|||
|
|||
/// <summary>
|
|||
/// 跳过多少条
|
|||
/// </summary>
|
|||
public int SkipCount => (PageIndex - 1) * PageSize; |
|||
|
|||
protected PagingBase() |
|||
{ |
|||
} |
|||
|
|||
public PagingBase(int pageIndex = 1, int pageSize = 10) |
|||
{ |
|||
PageIndex = pageIndex; |
|||
PageSize = pageSize; |
|||
} |
|||
|
|||
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) |
|||
{ |
|||
if (PageIndex < 1) |
|||
{ |
|||
yield return new ValidationResult( |
|||
"起始页必须大于等于1", |
|||
new[] { "PageIndex"} |
|||
); |
|||
} |
|||
|
|||
if (PageSize > MaxPageSize) |
|||
{ |
|||
yield return new ValidationResult( |
|||
$"每页最大记录数不能超过'{MaxPageSize}'", |
|||
new[] { "PageSize"} |
|||
); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,302 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.IO; |
|||
using System.Linq; |
|||
|
|||
namespace Lion.Abp.Extension |
|||
{ |
|||
/// <summary>
|
|||
/// 参数合法性检查类
|
|||
/// </summary>
|
|||
[DebuggerStepThrough] |
|||
public static class Guard |
|||
{ |
|||
/// <summary>
|
|||
/// 检查参数不能为空引用,
|
|||
/// 否则抛出<see cref="BeeNullException"/>异常。
|
|||
/// </summary>
|
|||
/// <param name="value"></param>
|
|||
/// <param name="valueName">参数名称</param>
|
|||
/// <exception cref="BeeNullException"></exception>
|
|||
public static T NotNull<T>(T value, string valueName) |
|||
{ |
|||
if (null == value) |
|||
{ |
|||
throw new ArgumentNullException(valueName); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查字符串不能为空引用或空字符串,
|
|||
/// 否则抛出<see cref="BeeNullOrEmptyException"/>异常
|
|||
/// 或<see cref="BeeLengthGreaterException"/>异常
|
|||
/// 或<see cref="BeeLengthLessException"/>异常。
|
|||
/// </summary>
|
|||
/// <param name="value"></param>
|
|||
/// <param name="valueName">参数名称。</param>
|
|||
/// <param name="maxLength">字符串允许的最大长度。</param>
|
|||
/// <param name="minLength">字符串允许的最小长度。0表示不限制最小长度</param>
|
|||
/// <exception cref="BeeNullOrEmptyException"></exception>
|
|||
/// <exception cref="BeeLengthGreaterException"></exception>
|
|||
/// <exception cref="BeeLengthLessException"></exception>
|
|||
public static string NotNullOrEmpty(string value, string valueName, int maxLength = int.MaxValue, |
|||
int minLength = 0) |
|||
{ |
|||
if (string.IsNullOrEmpty(value)) |
|||
{ |
|||
throw new ArgumentNullException(valueName); |
|||
} |
|||
|
|||
if (value.Length > maxLength) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(valueName); |
|||
} |
|||
|
|||
if (minLength > 0 && value.Length < minLength) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(valueName); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查字符串不能为空引用或全部为空白,
|
|||
/// 否则抛出<see cref="BeeNullOrWhiteSpaceException"/>异常
|
|||
/// 或<see cref="BeeLengthGreaterException"/>异常
|
|||
/// 或<see cref="BeeLengthLessException"/>异常。
|
|||
/// </summary>
|
|||
/// <param name="value">需检查的字符串</param>
|
|||
/// <param name="valueName">参数名称。</param>
|
|||
/// <param name="maxLength">字符串允许的最大长度。</param>
|
|||
/// <param name="minLength">字符串允许的最小长度。0表示不限制最小长度</param>
|
|||
/// <exception cref="BeeNullOrWhiteSpaceException"></exception>
|
|||
/// <exception cref="BeeLengthGreaterException"></exception>
|
|||
/// <exception cref="BeeLengthLessException"></exception>
|
|||
public static string NotNullOrWhiteSpace( |
|||
string value, |
|||
string valueName, |
|||
int maxLength = int.MaxValue, |
|||
int minLength = 0) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(value)) |
|||
{ |
|||
throw new ArgumentNullException(valueName); |
|||
} |
|||
|
|||
if (value.Length > maxLength) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(valueName); |
|||
} |
|||
|
|||
if (minLength > 0 && value.Length < minLength) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(valueName); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查字符串长度是否超过最大长度,或低于最小长度,
|
|||
/// 否则抛出<see cref="BeeLengthGreaterException"/>异常
|
|||
/// 或<see cref="BeeLengthLessException"/>异常。
|
|||
/// </summary>
|
|||
/// <param name="value">需检查的字符串。</param>
|
|||
/// <param name="valueName">参数名称。</param>
|
|||
/// <param name="maxLength">字符串允许的最大长度。</param>
|
|||
/// <param name="minLength">字符串要求的最小长度。0表示不限制最小长度</param>
|
|||
/// <exception cref="BeeLengthGreaterException"></exception>
|
|||
/// <exception cref="BeeLengthLessException"></exception>
|
|||
public static string Length(string value, string valueName, int maxLength = int.MaxValue, |
|||
int minLength = 0) |
|||
{ |
|||
if (string.IsNullOrEmpty(value)) |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
if (value.Length > maxLength) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(valueName); |
|||
} |
|||
|
|||
if (minLength > 0 && value.Length < minLength) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(valueName); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查Guid值不能为Guid.Empty,否则抛出<see cref="BeeEmptyGuidException"/>异常。
|
|||
/// </summary>
|
|||
/// <param name="value"></param>
|
|||
/// <param name="valueName">参数名称。</param>
|
|||
/// <exception cref="BeeEmptyGuidException"></exception>
|
|||
public static Guid NotEmpty( |
|||
Guid value, |
|||
string valueName) |
|||
{ |
|||
if (value == Guid.Empty) |
|||
{ |
|||
throw new ArgumentNullException(valueName); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查集合不能为空引用或空集合,
|
|||
/// 否则抛出<see cref="BeeCollectionNullOrEmptyException"/>异常。
|
|||
/// </summary>
|
|||
/// <typeparam name="T">集合项的类型。</typeparam>
|
|||
/// <param name="list"></param>
|
|||
/// <param name="valueName">参数名称。</param>
|
|||
/// <exception cref="BeeCollectionNullOrEmptyException"></exception>
|
|||
public static void NotNullOrEmpty<T>( |
|||
IReadOnlyList<T> list, |
|||
string valueName) |
|||
{ |
|||
if (null == list || !list.Any()) |
|||
{ |
|||
throw new ArgumentNullException(valueName); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查参数必须小于[或可等于,参数<paramref name="canEqual"/>]指定值,
|
|||
/// 否则抛出<see cref="BeeOutOfRangeException"/>异常。
|
|||
/// </summary>
|
|||
/// <typeparam name="T">参数类型。</typeparam>
|
|||
/// <param name="value"></param>
|
|||
/// <param name="valueName">参数名称。</param>
|
|||
/// <param name="target">要比较的值。</param>
|
|||
/// <param name="canEqual">是否可等于。</param>
|
|||
/// <exception cref="BeeOutOfRangeException"></exception>
|
|||
public static void LessThan<T>( |
|||
T value, |
|||
string valueName, |
|||
T target, |
|||
bool canEqual = false) |
|||
where T : IComparable<T> |
|||
{ |
|||
var flag = canEqual ? value.CompareTo(target) <= 0 : value.CompareTo(target) < 0; |
|||
if (!flag) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(valueName); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查参数必须大于[或可等于,参数<paramref name="canEqual"/>]指定值,
|
|||
/// 否则抛出<see cref="BeeOutOfRangeException"/>异常。
|
|||
/// </summary>
|
|||
/// <typeparam name="T">参数类型。</typeparam>
|
|||
/// <param name="value">需检查的参数。</param>
|
|||
/// <param name="valueName">参数名称。</param>
|
|||
/// <param name="target">要比较的值。</param>
|
|||
/// <param name="canEqual">是否可等于。</param>
|
|||
/// <exception cref="BeeOutOfRangeException"></exception>
|
|||
public static void GreaterThan<T>( |
|||
T value, |
|||
string valueName, |
|||
T target, |
|||
bool canEqual = false) |
|||
where T : IComparable<T> |
|||
{ |
|||
var flag = canEqual ? value.CompareTo(target) >= 0 : value.CompareTo(target) > 0; |
|||
if (!flag) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(valueName); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查参数必须在指定范围之间,否则抛出<see cref="BeeOutOfRangeException"/>异常。
|
|||
/// </summary>
|
|||
/// <typeparam name="T">参数类型。</typeparam>
|
|||
/// <param name="value">需检查的参数。</param>
|
|||
/// <param name="valueName">参数名称。</param>
|
|||
/// <param name="start">比较范围的起始值。</param>
|
|||
/// <param name="end">比较范围的结束值。</param>
|
|||
/// <param name="startEqual">是否可等于起始值</param>
|
|||
/// <param name="endEqual">是否可等于结束值</param>
|
|||
/// <exception cref="BeeOutOfRangeException">不在指定范围内时</exception>
|
|||
public static void Between<T>( |
|||
T value, |
|||
string valueName, |
|||
T start, |
|||
T end, |
|||
bool startEqual = false, |
|||
bool endEqual = false) |
|||
where T : IComparable<T> |
|||
{ |
|||
var flag = startEqual ? value.CompareTo(start) >= 0 : value.CompareTo(start) > 0; |
|||
if (!flag) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(valueName); |
|||
} |
|||
|
|||
flag = endEqual ? value.CompareTo(end) <= 0 : value.CompareTo(end) < 0; |
|||
if (!flag) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(valueName); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查指定路径的文件夹必须存在,
|
|||
/// 否则抛出<see cref="BeeDirectoryNotFoundException"/>异常
|
|||
/// 或 <see cref="BeeNullException"/>异常。
|
|||
/// </summary>
|
|||
/// <param name="directory">需检查的路径。</param>
|
|||
/// <param name="parameterName">参数名称。</param>
|
|||
/// <exception cref="BeeNullException">当文件夹路径为null或空时</exception>
|
|||
/// <exception cref="BeeDirectoryNotFoundException">当文件夹路径不存在时</exception>
|
|||
public static string DirectoryExists( |
|||
string directory, |
|||
string parameterName) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(directory)) |
|||
{ |
|||
throw new DirectoryNotFoundException(parameterName); |
|||
} |
|||
|
|||
if (!Directory.Exists(directory)) |
|||
{ |
|||
throw new DirectoryNotFoundException(directory); |
|||
} |
|||
|
|||
return directory; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查指定路径的文件必须存在,否则抛出<see cref="FileNotFoundException"/>异常。
|
|||
/// </summary>
|
|||
/// <param name="filename"></param>
|
|||
/// <param name="valueName">参数名称。</param>
|
|||
/// <exception cref="BeeNullOrWhiteSpaceException">当文件路径为null或空时</exception>
|
|||
/// <exception cref="BeeFileNotFoundException">当文件路径不存在时</exception>
|
|||
public static string FileExists( |
|||
string filename, |
|||
string valueName) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(filename)) |
|||
{ |
|||
throw new ArgumentNullException(valueName); |
|||
} |
|||
|
|||
if (!File.Exists(filename)) |
|||
{ |
|||
throw new FileNotFoundException(filename); |
|||
} |
|||
|
|||
return filename; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,164 @@ |
|||
using Newtonsoft.Json; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Net.Http; |
|||
using System.Net.Http.Headers; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Lion.Abp.Extension |
|||
{ |
|||
/// <summary>
|
|||
/// 基于IHttpClientFactory二次封装httpclient
|
|||
/// </summary>
|
|||
public static class HttpClientHelper |
|||
{ |
|||
|
|||
public static async Task<TResult> GetAsync<TResult>(this IHttpClientFactory _httpClientFactory, string clientName, string url, Dictionary<string, string> headers = null) where TResult : class |
|||
{ |
|||
try |
|||
{ |
|||
var client = _httpClientFactory.CreateClient(clientName); |
|||
if (headers != null && headers.Count > 0) |
|||
{ |
|||
foreach (var item in headers) |
|||
{ |
|||
client.DefaultRequestHeaders.Add(item.Key, item.Value); |
|||
} |
|||
|
|||
} |
|||
|
|||
client.DefaultRequestHeaders.CacheControl = CacheControlHeaderValue.Parse("no-cache"); |
|||
|
|||
//执行请求
|
|||
var response = await client.GetAsync(url); |
|||
var result = await response.Content.ReadAsStringAsync(); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
if (result != null && !string.IsNullOrEmpty(result)) |
|||
return JsonConvert.DeserializeObject<TResult>(result); |
|||
else |
|||
return default(TResult); |
|||
} |
|||
else |
|||
{ |
|||
if (string.IsNullOrEmpty(result)) |
|||
result = response.ReasonPhrase; |
|||
throw new Exception(result); |
|||
} |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
throw new Exception(e.Message); |
|||
} |
|||
} |
|||
|
|||
public static async Task<TResult> PostAsync<T, TResult>(this IHttpClientFactory _httpClientFactory, string clientName, string url, T obj, Dictionary<string, string> headers = null) where T : class where TResult : class |
|||
{ |
|||
var data = typeof(T).Name.ToLower() == "string" ? obj.ToString() : JsonConvert.SerializeObject(obj); |
|||
var client = _httpClientFactory.CreateClient(clientName); |
|||
if (headers != null && headers.Count > 0) |
|||
{ |
|||
foreach (var item in headers) |
|||
{ |
|||
client.DefaultRequestHeaders.Add(item.Key, item.Value); |
|||
} |
|||
} |
|||
|
|||
client.DefaultRequestHeaders.CacheControl = CacheControlHeaderValue.Parse("no-cache"); |
|||
//post 参数
|
|||
var content = new StringContent(data, Encoding.UTF8, "application/json"); |
|||
//执行请求
|
|||
var response = await client.PostAsync(url, content); |
|||
|
|||
var result = await response.Content.ReadAsStringAsync(); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
if (result != null && !string.IsNullOrEmpty(result)) |
|||
return JsonConvert.DeserializeObject<TResult>(result); |
|||
else |
|||
return default(TResult); |
|||
} |
|||
else |
|||
{ |
|||
if (string.IsNullOrEmpty(result)) |
|||
result = response.ReasonPhrase; |
|||
|
|||
throw new Exception(result); |
|||
} |
|||
} |
|||
|
|||
public static async Task<TResult> PutAsync<T, TResult>(this IHttpClientFactory _httpClientFactory, string clientName, string url, T obj, Dictionary<string, string> headers = null) where T : class where TResult : class |
|||
{ |
|||
var data = typeof(T).Name.ToLower() == "string" ? obj.ToString() : JsonConvert.SerializeObject(obj); |
|||
var client = _httpClientFactory.CreateClient(clientName); |
|||
if (headers != null && headers.Count > 0) |
|||
{ |
|||
foreach (var item in headers) |
|||
{ |
|||
client.DefaultRequestHeaders.Add(item.Key, item.Value); |
|||
} |
|||
} |
|||
|
|||
client.DefaultRequestHeaders.CacheControl = CacheControlHeaderValue.Parse("no-cache"); |
|||
//post 参数
|
|||
var content = new StringContent(data, Encoding.UTF8, "application/json"); |
|||
//执行请求
|
|||
var response = await client.PutAsync(url, content); |
|||
|
|||
var result = await response.Content.ReadAsStringAsync(); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
if (result != null && !string.IsNullOrEmpty(result)) |
|||
return JsonConvert.DeserializeObject<TResult>(result); |
|||
else |
|||
return default(TResult); |
|||
} |
|||
else |
|||
{ |
|||
if (string.IsNullOrEmpty(result)) |
|||
result = response.ReasonPhrase; |
|||
|
|||
throw new Exception(result); |
|||
} |
|||
} |
|||
|
|||
public static async Task<TResult> DeleteAsync<TResult>(this IHttpClientFactory _httpClientFactory, string clientName, string url, Dictionary<string, string> headers = null) where TResult : class |
|||
{ |
|||
try |
|||
{ |
|||
var client = _httpClientFactory.CreateClient(clientName); |
|||
if (headers != null && headers.Count > 0) |
|||
{ |
|||
foreach (var item in headers) |
|||
{ |
|||
client.DefaultRequestHeaders.Add(item.Key, item.Value); |
|||
} |
|||
} |
|||
|
|||
client.DefaultRequestHeaders.CacheControl = CacheControlHeaderValue.Parse("no-cache"); |
|||
|
|||
//执行请求
|
|||
var response = await client.DeleteAsync(url); |
|||
var result = await response.Content.ReadAsStringAsync(); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
if (result != null && !string.IsNullOrEmpty(result)) |
|||
return JsonConvert.DeserializeObject<TResult>(result); |
|||
else |
|||
return default(TResult); |
|||
} |
|||
else |
|||
{ |
|||
if (string.IsNullOrEmpty(result)) |
|||
result = response.ReasonPhrase; |
|||
throw new Exception(result); |
|||
} |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
throw new Exception(e.Message); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net5.0</TargetFramework> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="5.0.0" /> |
|||
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> |
|||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> |
|||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> |
|||
<PackageReference Include="Volo.Abp.Autofac" Version="$(AbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Json" Version="$(AbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Validation" Version="$(AbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="$(AbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.AutoMapper" Version="$(AbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.ObjectMapping" Version="$(AbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -0,0 +1,27 @@ |
|||
namespace System |
|||
{ |
|||
/// <summary>
|
|||
/// 布尔值<see cref="Boolean"/>类型的扩展辅助操作类
|
|||
/// </summary>
|
|||
public static class BooleanExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 把布尔值转换为小写字符串
|
|||
/// </summary>
|
|||
public static string ToLower(this bool value) |
|||
{ |
|||
return value.ToString().ToLower(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 如果条件成立,则抛出异常
|
|||
/// </summary>
|
|||
public static void TrueThrow(this bool flag, Exception exception) |
|||
{ |
|||
if (flag) |
|||
{ |
|||
throw exception; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
using System.Linq; |
|||
using Lion.Abp.Extension; |
|||
|
|||
namespace System.Collections.Generic |
|||
{ |
|||
/// <summary>
|
|||
/// 集合扩展方法
|
|||
/// </summary>
|
|||
public static class CollectionExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 如果条件成立,添加项
|
|||
/// </summary>
|
|||
public static void AddIf<T>(this ICollection<T> collection, T value, bool flag) |
|||
{ |
|||
Guard.NotNull(collection, nameof(collection)); |
|||
if (flag) |
|||
{ |
|||
collection.Add(value); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 如果条件成立,添加项
|
|||
/// </summary>
|
|||
public static void AddIf<T>(this ICollection<T> collection, T value, Func<bool> func) |
|||
{ |
|||
Guard.NotNull(collection, nameof(collection)); |
|||
if (func()) |
|||
{ |
|||
collection.Add(value); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取对象,不存在对使用委托添加对象
|
|||
/// </summary>
|
|||
public static T GetOrAdd<T>(this ICollection<T> collection, Func<T, bool> selector, Func<T> factory) |
|||
{ |
|||
Guard.NotNull(collection, nameof(collection)); |
|||
T item = collection.FirstOrDefault(selector); |
|||
if (item == null) |
|||
{ |
|||
item = factory(); |
|||
collection.Add(item); |
|||
} |
|||
|
|||
return item; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 判断集合是否为null或空集合
|
|||
/// </summary>
|
|||
public static bool IsNullOrEmpty<T>(this ICollection<T> collection) |
|||
{ |
|||
return collection == null || collection.Count == 0; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 交换两项的位置
|
|||
/// </summary>
|
|||
public static void Swap<T>(this List<T> list, int index1, int index2) |
|||
{ |
|||
Guard.Between(index1, nameof(index1), 0, list.Count, true); |
|||
Guard.Between(index2, nameof(index2), 0, list.Count, true); |
|||
|
|||
if (index1 == index2) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
T tmp = list[index1]; |
|||
list[index1] = list[index2]; |
|||
list[index2] = tmp; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,199 @@ |
|||
using System.Linq; |
|||
using System.Text; |
|||
using Lion.Abp.Extension; |
|||
namespace System.Collections.Generic |
|||
{ |
|||
/// <summary>
|
|||
/// Enumerable集合扩展方法
|
|||
/// </summary>
|
|||
public static class EnumerableExtensions |
|||
{ |
|||
/// <summary>断言集合中的元素符合指定表达式,否则抛出异常。</summary>
|
|||
/// <typeparam name="T">集合项类型</typeparam>
|
|||
/// <param name="source">源集合</param>
|
|||
/// <param name="predicate">元素判断表达式</param>
|
|||
/// <param name="errorSelector">异常选择器</param>
|
|||
/// <returns>筛选过的集合</returns>
|
|||
public static IEnumerable<T> Assert<T>(this IEnumerable<T> source, Func<T, bool> predicate, |
|||
Func<T, Exception> errorSelector = null) |
|||
{ |
|||
foreach (var item in source) |
|||
{ |
|||
var success = predicate(item); |
|||
if (!success) |
|||
{ |
|||
throw errorSelector?.Invoke(item) ?? |
|||
new InvalidOperationException("集合中包含无效的元素。"); |
|||
} |
|||
|
|||
yield return item; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 打乱一个集合的项顺序,将一个集合洗牌
|
|||
/// </summary>
|
|||
public static IEnumerable<TSource> Shuffle<TSource>(this IEnumerable<TSource> source) |
|||
{ |
|||
// ReSharper disable PossibleMultipleEnumeration
|
|||
|
|||
Guard.NotNull(source, nameof(source)); |
|||
return source.OrderBy(m => Guid.NewGuid()); |
|||
|
|||
// ReSharper restore PossibleMultipleEnumeration
|
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将集合展开并分别转换成字符串,再以指定的分隔符衔接,拼成一个字符串返回。默认分隔符为逗号。
|
|||
/// </summary>
|
|||
/// <param name="collection">要处理的集合</param>
|
|||
/// <param name="separator">分隔符,默认为逗号</param>
|
|||
/// <returns>拼接后的字符串</returns>
|
|||
public static string ExpandAndToString<T>(this IEnumerable<T> collection, string separator = ",") |
|||
{ |
|||
return collection.ExpandAndToString(item => item?.ToString() ?? string.Empty, separator); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 循环集合的每一项,调用委托生成字符串,返回合并后的字符串。默认分隔符为逗号
|
|||
/// </summary>
|
|||
/// <param name="collection">待处理的集合</param>
|
|||
/// <param name="itemFormatFunc">单个集合项的转换委托</param>
|
|||
/// <param name="separator">分隔符,默认为逗号</param>
|
|||
/// <typeparam name="T">泛型类型</typeparam>
|
|||
/// <returns></returns>
|
|||
public static string ExpandAndToString<T>( |
|||
this IEnumerable<T> collection, |
|||
Func<T, string> itemFormatFunc, |
|||
string separator = ",") |
|||
{ |
|||
collection = collection as IList<T> ?? collection.ToList(); |
|||
Guard.NotNull(itemFormatFunc, nameof(itemFormatFunc)); |
|||
|
|||
if (!collection.Any()) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
var sb = new StringBuilder(); |
|||
var i = 0; |
|||
var count = collection.Count(); |
|||
foreach (var item in collection) |
|||
{ |
|||
if (i == count - 1) |
|||
{ |
|||
sb.Append(itemFormatFunc(item)); |
|||
} |
|||
else |
|||
{ |
|||
sb.Append(itemFormatFunc(item) + separator); |
|||
} |
|||
|
|||
i++; |
|||
} |
|||
|
|||
return sb.ToString(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 集合是否为空
|
|||
/// </summary>
|
|||
/// <param name="collection"> 要处理的集合 </param>
|
|||
/// <typeparam name="T"> 动态类型 </typeparam>
|
|||
/// <returns> 为空返回True,不为空返回False </returns>
|
|||
public static bool IsEmpty<T>(this IEnumerable<T> collection) |
|||
{ |
|||
collection = collection as IList<T> ?? collection.ToList(); |
|||
return !collection.Any(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据第三方条件是否为真来决定是否执行指定条件的查询
|
|||
/// </summary>
|
|||
/// <param name="source"> 要查询的源 </param>
|
|||
/// <param name="predicate"> 查询条件 </param>
|
|||
/// <param name="condition"> 第三方条件 </param>
|
|||
/// <typeparam name="T"> 动态类型 </typeparam>
|
|||
/// <returns> 查询的结果 </returns>
|
|||
public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool condition) |
|||
{ |
|||
Guard.NotNull(predicate, nameof(predicate)); |
|||
source = source as IList<T> ?? source.ToList(); |
|||
|
|||
return condition ? source.Where(predicate) : source; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将字符串集合按指定前缀排序
|
|||
/// </summary>
|
|||
public static IEnumerable<T> OrderByPrefixes<T>(this IEnumerable<T> source, Func<T, string> keySelector, |
|||
params string[] prefixes) |
|||
{ |
|||
var all = source.OrderBy(keySelector).ToList(); |
|||
var result = new List<T>(); |
|||
foreach (var prefix in prefixes) |
|||
{ |
|||
var tmpList = all.Where(m => keySelector(m).StartsWith(prefix)).OrderBy(keySelector).ToList(); |
|||
all = all.Except(tmpList).ToList(); |
|||
result.AddRange(tmpList); |
|||
} |
|||
|
|||
result.AddRange(all); |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据指定条件返回集合中不重复的元素
|
|||
/// </summary>
|
|||
/// <typeparam name="T">动态类型</typeparam>
|
|||
/// <typeparam name="TKey">动态筛选条件类型</typeparam>
|
|||
/// <param name="source">要操作的源</param>
|
|||
/// <param name="keySelector">重复数据筛选条件</param>
|
|||
/// <returns>不重复元素的集合</returns>
|
|||
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector) |
|||
{ |
|||
Guard.NotNull(keySelector, nameof(keySelector)); |
|||
source = source as IList<T> ?? source.ToList(); |
|||
|
|||
return source.GroupBy(keySelector).Select(group => group.First()); |
|||
} |
|||
|
|||
#region Internal
|
|||
|
|||
internal static int? TryGetCollectionCount<T>(this IEnumerable<T> source) |
|||
{ |
|||
switch (source) |
|||
{ |
|||
case null: |
|||
throw new ArgumentNullException(nameof(source)); |
|||
case ICollection<T> collection: |
|||
return collection.Count; |
|||
case IReadOnlyCollection<T> collection: |
|||
return collection.Count; |
|||
default: |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
static int CountUpTo<T>(this IEnumerable<T> source, int max) |
|||
{ |
|||
if (source == null) throw new ArgumentNullException(nameof(source)); |
|||
if (max < 0) |
|||
throw new ArgumentOutOfRangeException(nameof(max), "最大计数参数不能为负。"); |
|||
|
|||
var count = 0; |
|||
|
|||
using (var e = source.GetEnumerator()) |
|||
{ |
|||
while (count < max && e.MoveNext()) |
|||
{ |
|||
count++; |
|||
} |
|||
} |
|||
|
|||
return count; |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
using System.Globalization; |
|||
using System.Linq; |
|||
|
|||
namespace System |
|||
{ |
|||
/// <summary>
|
|||
/// 时间扩展操作类
|
|||
/// </summary>
|
|||
public static class DateTimeExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 当前时间是否周末
|
|||
/// </summary>
|
|||
/// <param name="dateTime">时间点</param>
|
|||
/// <returns></returns>
|
|||
public static bool IsWeekend(this DateTime dateTime) |
|||
{ |
|||
DayOfWeek[] weeks = { DayOfWeek.Saturday, DayOfWeek.Sunday }; |
|||
return weeks.Contains(dateTime.DayOfWeek); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 当前时间是否工作日
|
|||
/// </summary>
|
|||
/// <param name="dateTime">时间点</param>
|
|||
/// <returns></returns>
|
|||
public static bool IsWeekday(this DateTime dateTime) |
|||
{ |
|||
DayOfWeek[] weeks = { DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday }; |
|||
return weeks.Contains(dateTime.DayOfWeek); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取时间相对唯一字符串
|
|||
/// </summary>
|
|||
/// <param name="dateTime"></param>
|
|||
/// <param name="millisecond">是否使用毫秒</param>
|
|||
/// <returns></returns>
|
|||
public static string ToUniqueString(this DateTime dateTime, bool millisecond = false) |
|||
{ |
|||
var seconds = dateTime.Hour * 3600 + dateTime.Minute * 60 + dateTime.Second; |
|||
var value = $"{dateTime:yyyy}{dateTime.DayOfYear}{seconds}"; |
|||
if (millisecond) |
|||
{ |
|||
return value + dateTime.ToString("fff"); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将时间转换为JS时间格式(Date.getTime())
|
|||
/// </summary>
|
|||
/// <param name="dateTime"></param>
|
|||
/// <param name="millisecond">是否使用毫秒</param>
|
|||
public static string ToJsGetTime(this DateTime dateTime, bool millisecond = true) |
|||
{ |
|||
var utc = dateTime.ToUniversalTime(); |
|||
var span = utc.Subtract(new DateTime(1970, 1, 1)); |
|||
return Math.Round(millisecond ? span.TotalMilliseconds : span.TotalSeconds).ToString(CultureInfo.InvariantCulture); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将JS时间格式的数值转换为时间
|
|||
/// </summary>
|
|||
public static DateTime FromJsGetTime(this long jsTime) |
|||
{ |
|||
var length = jsTime.ToString().Length; |
|||
if (!(length == 10 || length == 13)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(null, "JS时间数值的长度不正确,必须为10位或13位"); |
|||
} |
|||
var start = new DateTime(1970, 1, 1); |
|||
var result = length == 10 ? start.AddSeconds(jsTime) : start.AddMilliseconds(jsTime); |
|||
return result.ToUniversalTime(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,199 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Specialized; |
|||
using System.ComponentModel; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
|
|||
namespace System |
|||
{ |
|||
/// <summary>
|
|||
/// 枚举<see cref="Enum"/>的扩展辅助操作方法
|
|||
/// </summary>
|
|||
public static class EnumExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 获取枚举项上的<see cref="DescriptionAttribute"/>特性的文字描述
|
|||
/// </summary>
|
|||
/// <param name="value"></param>
|
|||
/// <returns></returns>
|
|||
public static string ToDescription(this Enum value) |
|||
{ |
|||
var type = value.GetType(); |
|||
var member = type.GetMember(value.ToString()).FirstOrDefault(); |
|||
|
|||
return member != null ? member.GetDescription() : value.ToString(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 枚举遍历,返回枚举的名称、值、特性
|
|||
/// </summary>
|
|||
/// <param name="enumType">枚举类型</param>
|
|||
/// <param name="action">回调函数</param>
|
|||
private static void Each(this Type enumType, Action<string, string, string, object> action) |
|||
{ |
|||
if (enumType.BaseType != typeof(Enum)) |
|||
{ |
|||
return; |
|||
} |
|||
var arr = Enum.GetValues(enumType); |
|||
foreach (var name in arr) |
|||
{ |
|||
var currentEnum = Enum.Parse(enumType, name.ToString()); |
|||
var value = Convert.ToInt32(Enum.Parse(enumType, name.ToString())); |
|||
var fieldInfo = enumType.GetField(name.ToString()); |
|||
var description = ""; |
|||
if (fieldInfo != null) |
|||
{ |
|||
var attr = Attribute.GetCustomAttribute(fieldInfo, |
|||
typeof(DescriptionAttribute), false) as DescriptionAttribute; |
|||
if (attr != null) |
|||
{ |
|||
description = attr.Description; |
|||
} |
|||
} |
|||
action(name.ToString(), value.ToString(), description, currentEnum); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据枚举类型值返回枚举定义Description属性
|
|||
/// </summary>
|
|||
/// <param name="value"></param>
|
|||
/// <param name="enumType"></param>
|
|||
/// <returns></returns>
|
|||
public static string ToEnumDescriptionString(this short value, Type enumType) |
|||
{ |
|||
var nvc = new NameValueCollection(); |
|||
var typeDescription = typeof(DescriptionAttribute); |
|||
var fields = enumType.GetFields(); |
|||
foreach (var field in fields) |
|||
{ |
|||
if (field.FieldType.IsEnum) |
|||
{ |
|||
var strValue = ((int)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null)).ToString(); |
|||
var arr = field.GetCustomAttributes(typeDescription, true); |
|||
string strText; |
|||
if (arr.Length > 0) |
|||
{ |
|||
var aa = (DescriptionAttribute)arr[0]; |
|||
strText = aa.Description; |
|||
} |
|||
else |
|||
{ |
|||
strText = ""; |
|||
} |
|||
nvc.Add(strValue, strText); |
|||
} |
|||
} |
|||
return nvc[value.ToString()]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将指定枚举转换为字典.
|
|||
/// 枚举的Description为字典的Key,枚举的Value为字典的Value
|
|||
/// </summary>
|
|||
/// <typeparam name="T">指定枚举</typeparam>
|
|||
private static List<KeyValuePair<string, string>> GetEnumTypeValueList<T>() |
|||
{ |
|||
var items = new List<KeyValuePair<string, string>>(); |
|||
typeof(T).Each((name, value, description, enumObj) => |
|||
items.Add(new KeyValuePair<string, string>(description, value))); |
|||
return items; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将指定枚举转换为字典.
|
|||
/// 枚举的Description为字典的Key,枚举为字典的Value
|
|||
/// </summary>
|
|||
/// <typeparam name="T">指定枚举</typeparam>
|
|||
private static List<KeyValuePair<string, T>> GetEnumTypeList<T>() |
|||
{ |
|||
var items = new List<KeyValuePair<string, T>>(); |
|||
typeof(T).Each((name, value, description, enumObj) => |
|||
items.Add(new KeyValuePair<string, T>(description, (T)enumObj))); |
|||
return items; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将指定枚举转换为字典.
|
|||
/// 枚举的Description为字典的Key,枚举的Name为字典的Value
|
|||
/// </summary>
|
|||
/// <typeparam name="T">指定枚举</typeparam>
|
|||
public static List<KeyValuePair<string, string>> GetEnumTypeDescriptionNameList<T>() |
|||
{ |
|||
var items = new List<KeyValuePair<string, string>>(); |
|||
typeof(T).Each((name, value, description, enumObj) => items.Add(new KeyValuePair<string, string>(description, name))); |
|||
return items; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将指定枚举转换为字典.
|
|||
/// 枚举的Name为字典的Key,枚举的Description为字典的Value
|
|||
/// </summary>
|
|||
/// <typeparam name="T">指定枚举</typeparam>
|
|||
public static List<KeyValuePair<string, string>> GetEnumTypeValueNameList<T>() |
|||
{ |
|||
var items = new List<KeyValuePair<string, string>>(); |
|||
typeof(T).Each((name, value, description, enumObj) => items.Add(new KeyValuePair<string, string>(name, description))); |
|||
return items; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将指定枚举转换为字典.
|
|||
/// 枚举的Name为字典的Key,枚举的Description为字典的Value
|
|||
/// </summary>
|
|||
/// <typeparam name="TModel">指定枚举</typeparam>
|
|||
public static List<KeyValuePair<string, string>> GetStringKeyValueList<TModel>() where TModel : Enum |
|||
{ |
|||
var keyValuePairList = new List<KeyValuePair<string, string>>(); |
|||
var values = Enum.GetValues(typeof(TModel)); |
|||
var modelArray = new TModel[values.Length]; |
|||
values.CopyTo(modelArray, 0); |
|||
foreach (TModel model in modelArray) |
|||
keyValuePairList.Add(new KeyValuePair<string, string>(model.ToString(), model.ToString())); |
|||
return keyValuePairList; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将指定枚举转换为字典.
|
|||
/// 枚举的Description为字典的Key,枚举为字典的Value
|
|||
/// </summary>
|
|||
/// <typeparam name="TModel">指定枚举</typeparam>
|
|||
public static List<KeyValuePair<string, TModel>> GetEnumKeyValueList<TModel>() where TModel : Enum |
|||
{ |
|||
var enumTypeList = GetEnumTypeList<TModel>(); |
|||
var keyValuePairList = new List<KeyValuePair<string, TModel>>(); |
|||
foreach (KeyValuePair<string, TModel> keyValuePair in enumTypeList) |
|||
keyValuePairList.Add(new KeyValuePair<string, TModel>(keyValuePair.Key, keyValuePair.Value)); |
|||
return keyValuePairList; |
|||
} |
|||
|
|||
public static List<KeyValuePair<string, string>> GetEntityDoubleStringKeyValueList<TModel>() |
|||
{ |
|||
var enumTypeList = GetEnumTypeValueList<TModel>(); |
|||
var keyValuePairList = new List<KeyValuePair<string, string>>(); |
|||
foreach (KeyValuePair<string, string> keyValuePair in enumTypeList) |
|||
keyValuePairList.Add(new KeyValuePair<string, string>(keyValuePair.Key, keyValuePair.Value)); |
|||
return keyValuePairList; |
|||
} |
|||
|
|||
public static List<KeyValuePair<string, int>> GetEntityStringIntKeyValueList<TModel>() |
|||
{ |
|||
List<KeyValuePair<string, string>> enumTypeList = GetEnumTypeValueList<TModel>(); |
|||
List<KeyValuePair<string, int>> keyValuePairList = new List<KeyValuePair<string, int>>(); |
|||
foreach (KeyValuePair<string, string> keyValuePair in enumTypeList) |
|||
keyValuePairList.Add(new KeyValuePair<string, int>(keyValuePair.Key, Convert.ToInt32(keyValuePair.Value))); |
|||
return keyValuePairList; |
|||
} |
|||
|
|||
public static List<KeyValuePair<int, int>> GetEntityDoubleIntKeyValueList<TModel>() |
|||
{ |
|||
List<KeyValuePair<string, string>> enumTypeList = GetEnumTypeValueList<TModel>(); |
|||
List<KeyValuePair<int, int>> keyValuePairList = new List<KeyValuePair<int, int>>(); |
|||
foreach (KeyValuePair<string, string> keyValuePair in enumTypeList) |
|||
keyValuePairList.Add(new KeyValuePair<int, int>(Convert.ToInt32(keyValuePair.Key), Convert.ToInt32(keyValuePair.Value))); |
|||
return keyValuePairList; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
using System.Runtime.ExceptionServices; |
|||
using System.Text; |
|||
|
|||
namespace System |
|||
{ |
|||
/// <summary>
|
|||
/// 异常操作扩展
|
|||
/// </summary>
|
|||
public static class ExceptionExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 格式化异常消息
|
|||
/// </summary>
|
|||
/// <param name="e">异常对象</param>
|
|||
/// <param name="isHideStackTrace">是否隐藏异常规模信息</param>
|
|||
/// <returns>格式化后的异常信息字符串</returns>
|
|||
public static string FormatMessage(this Exception e, bool isHideStackTrace = false) |
|||
{ |
|||
var sb = new StringBuilder(); |
|||
var count = 0; |
|||
var appString = string.Empty; |
|||
while (e != null) |
|||
{ |
|||
if (count > 0) |
|||
{ |
|||
appString += " "; |
|||
} |
|||
sb.AppendLine($"{appString}异常消息:{e.Message}"); |
|||
sb.AppendLine($"{appString}异常类型:{e.GetType().FullName}"); |
|||
sb.AppendLine($"{appString}异常方法:{(e.TargetSite == null ? null : e.TargetSite.Name)}"); |
|||
sb.AppendLine($"{appString}异常源:{e.Source}"); |
|||
if (!isHideStackTrace && e.StackTrace != null) |
|||
{ |
|||
sb.AppendLine($"{appString}异常堆栈:{e.StackTrace}"); |
|||
} |
|||
if (e.InnerException != null) |
|||
{ |
|||
sb.AppendLine($"{appString}内部异常:"); |
|||
count++; |
|||
e = e.InnerException; |
|||
} |
|||
} |
|||
return sb.ToString(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将异常重新抛出
|
|||
/// </summary>
|
|||
public static void ReThrow(this Exception exception) |
|||
{ |
|||
ExceptionDispatchInfo.Capture(exception).Throw(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 如果条件成立,则抛出异常
|
|||
/// </summary>
|
|||
public static void ThrowIf(this Exception exception, bool isThrow) |
|||
{ |
|||
if (isThrow) |
|||
{ |
|||
throw exception; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 如果条件成立,则抛出异常
|
|||
/// </summary>
|
|||
public static void ThrowIf(this Exception exception, Func<bool> isThrowFunc) |
|||
{ |
|||
if (isThrowFunc()) |
|||
{ |
|||
throw exception; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
using System.Linq.Expressions; |
|||
using Lion.Abp.Extension; |
|||
|
|||
namespace System.Linq |
|||
{ |
|||
/// <summary>
|
|||
/// IQueryable集合扩展方法
|
|||
/// </summary>
|
|||
public static class QueryableExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 根据第三方条件是否为真来决定是否执行指定条件的查询
|
|||
/// </summary>
|
|||
/// <param name="source"> 要查询的源 </param>
|
|||
/// <param name="predicate"> 查询条件 </param>
|
|||
/// <param name="condition"> 第三方条件 </param>
|
|||
/// <typeparam name="T"> 动态类型 </typeparam>
|
|||
/// <returns> 查询的结果 </returns>
|
|||
public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate, |
|||
bool condition) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
Guard.NotNull(predicate, nameof(predicate)); |
|||
|
|||
return condition ? source.Where(predicate) : source; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using System.Diagnostics; |
|||
using Lion.Abp.Extension; |
|||
|
|||
namespace System.Reflection |
|||
{ |
|||
/// <summary>
|
|||
/// 程序集扩展操作类
|
|||
/// </summary>
|
|||
public static class AssemblyExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 获取程序集的产品版本
|
|||
/// </summary>
|
|||
public static string GetProductVersion(this Assembly assembly) |
|||
{ |
|||
Guard.NotNull(assembly, nameof(assembly)); |
|||
var info = FileVersionInfo.GetVersionInfo(assembly.Location); |
|||
var version = info.ProductVersion; |
|||
if (version.Contains("+")) |
|||
{ |
|||
version = version.ReplaceRegex(@"\+(\w+)?", ""); |
|||
} |
|||
return version; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
using System.ComponentModel; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System.Linq; |
|||
|
|||
namespace System.Reflection |
|||
{ |
|||
/// <summary>
|
|||
/// 成员<see cref="MemberInfo"/>的扩展辅助操作方法
|
|||
/// </summary>
|
|||
public static class MemberInfoExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 获取成员元数据的Description特性描述信息。
|
|||
/// </summary>
|
|||
/// <param name="member">成员元数据对象。</param>
|
|||
/// <param name="inherit">是否搜索成员的继承链以查找描述特性。</param>
|
|||
/// <returns>返回Description特性描述信息,如不存在则返回成员的名称。</returns>
|
|||
public static string GetDescription(this MemberInfo member, bool inherit = true) |
|||
{ |
|||
var desc = member.GetAttribute<DescriptionAttribute>(inherit); |
|||
if (desc != null) |
|||
{ |
|||
return desc.Description; |
|||
} |
|||
|
|||
var displayName = member.GetAttribute<DisplayNameAttribute>(inherit); |
|||
if (displayName != null) |
|||
{ |
|||
return displayName.DisplayName; |
|||
} |
|||
|
|||
var display = member.GetAttribute<DisplayAttribute>(inherit); |
|||
return display != null ? display.Name : member.Name; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查指定指定类型成员中是否存在指定的Attribute特性。
|
|||
/// </summary>
|
|||
/// <typeparam name="T">要检查的Attribute特性类型。</typeparam>
|
|||
/// <param name="memberInfo">要检查的类型成员</param>
|
|||
/// <param name="inherit">是否从继承中查找</param>
|
|||
/// <returns>是否存在</returns>
|
|||
public static bool HasAttribute<T>(this MemberInfo memberInfo, bool inherit = true) where T : Attribute |
|||
{ |
|||
return memberInfo.IsDefined(typeof(T), inherit); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 从类型成员获取指定Attribute特性
|
|||
/// </summary>
|
|||
/// <typeparam name="T">Attribute特性类型</typeparam>
|
|||
/// <param name="memberInfo">类型类型成员</param>
|
|||
/// <param name="inherit">是否从继承中查找</param>
|
|||
/// <returns>存在返回第一个,不存在返回null</returns>
|
|||
public static T GetAttribute<T>(this MemberInfo memberInfo, bool inherit = true) where T : Attribute |
|||
{ |
|||
var attributes = memberInfo.GetCustomAttributes(typeof(T), inherit); |
|||
return attributes.FirstOrDefault() as T; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 从类型成员获取指定Attribute特性。
|
|||
/// </summary>
|
|||
/// <typeparam name="T">Attribute特性类型。</typeparam>
|
|||
/// <param name="memberInfo">类型类型成员。</param>
|
|||
/// <param name="inherit">是否从继承中查找。</param>
|
|||
/// <returns>返回所有指定Attribute特性的数组。</returns>
|
|||
public static T[] GetAttributes<T>(this MemberInfo memberInfo, bool inherit = true) where T : Attribute |
|||
{ |
|||
return memberInfo.GetCustomAttributes(typeof(T), inherit).Cast<T>().ToArray(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace System.Reflection |
|||
{ |
|||
/// <summary>
|
|||
/// 方法<see cref="MethodInfo"/>的扩展辅助操作方法
|
|||
/// </summary>
|
|||
public static class MethodInfoExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 方法是否是异步
|
|||
/// </summary>
|
|||
public static bool IsAsync(this MethodInfo method) |
|||
{ |
|||
return (method.ReturnType == typeof(Task<>) |
|||
|| method.ReturnType.IsGenericType |
|||
&& method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)) |
|||
|| method.ReturnType == typeof(Task); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 返回当前方法信息是否是重写方法
|
|||
/// </summary>
|
|||
/// <param name="method">要判断的方法信息</param>
|
|||
/// <returns>是否是重写方法</returns>
|
|||
public static bool IsOverridden(this MethodInfo method) |
|||
{ |
|||
return method.GetBaseDefinition().DeclaringType != method.DeclaringType; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using System.Linq; |
|||
|
|||
namespace System.Reflection |
|||
{ |
|||
/// <summary>
|
|||
/// 属性<see cref="MethodInfo"/>的扩展辅助操作方法
|
|||
/// </summary>
|
|||
public static class PropertyInfoExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 返回当前属性信息是否为virtual
|
|||
/// </summary>
|
|||
public static bool IsVirtual(this PropertyInfo property) |
|||
{ |
|||
var accessor = property.GetAccessors().FirstOrDefault(); |
|||
if (accessor == null) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return accessor.IsVirtual && !accessor.IsFinal; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,981 @@ |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.Globalization; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Text.RegularExpressions; |
|||
using System.Web; |
|||
using Lion.Abp.Extension; |
|||
using Newtonsoft.Json; |
|||
|
|||
namespace System |
|||
{ |
|||
/// <summary>
|
|||
/// 字符串<see cref="string"/>类型的扩展辅助操作类
|
|||
/// </summary>
|
|||
[DebuggerStepThrough] |
|||
public static class StringExtensions |
|||
{ |
|||
#region 正则表达式
|
|||
|
|||
/// <summary>
|
|||
/// 指示所指定的正则表达式在指定的输入字符串中是否找到了匹配项
|
|||
/// </summary>
|
|||
/// <param name="value">要搜索匹配项的字符串</param>
|
|||
/// <param name="pattern">要匹配的正则表达式模式</param>
|
|||
/// <param name="isContains">是否包含,否则全匹配</param>
|
|||
/// <returns>如果正则表达式找到匹配项,则为 true;否则,为 false</returns>
|
|||
public static bool IsMatch(this string value, string pattern, bool isContains = true) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return isContains |
|||
? Regex.IsMatch(value, pattern) |
|||
: Regex.Match(value, pattern).Success; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 在指定的输入字符串中搜索指定的正则表达式的第一个匹配项
|
|||
/// </summary>
|
|||
/// <param name="value">要搜索匹配项的字符串</param>
|
|||
/// <param name="pattern">要匹配的正则表达式模式</param>
|
|||
/// <returns>一个对象,包含有关匹配项的信息</returns>
|
|||
public static string Match(this string value, string pattern) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return Regex.Match(value, pattern).Value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 在指定的输入字符串中匹配并替换符合指定正则表达式的子串
|
|||
/// </summary>
|
|||
public static string ReplaceRegex(this string value, string pattern, string replacement) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return Regex.Replace(value, pattern, replacement); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 在指定的输入字符串中搜索指定的正则表达式的所有匹配项的字符串集合
|
|||
/// </summary>
|
|||
/// <param name="value"> 要搜索匹配项的字符串 </param>
|
|||
/// <param name="pattern"> 要匹配的正则表达式模式 </param>
|
|||
/// <returns> 一个集合,包含有关匹配项的字符串值 </returns>
|
|||
public static IEnumerable<string> Matches(this string value, string pattern) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
return new string[] { }; |
|||
} |
|||
|
|||
var matches = Regex.Matches(value, pattern); |
|||
return from Match match in matches select match.Value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 在指定的输入字符串中匹配第一个数字字符串
|
|||
/// </summary>
|
|||
public static string MatchFirstNumber(this string value) |
|||
{ |
|||
var matches = Regex.Matches(value, @"\d+"); |
|||
if (matches.Count == 0) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
return matches[0].Value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 在指定字符串中匹配最后一个数字字符串
|
|||
/// </summary>
|
|||
public static string MatchLastNumber(this string value) |
|||
{ |
|||
var matches = Regex.Matches(value, @"\d+"); |
|||
if (matches.Count == 0) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
return matches[matches.Count - 1].Value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 在指定字符串中匹配所有数字字符串
|
|||
/// </summary>
|
|||
public static IEnumerable<string> MatchNumbers(this string value) |
|||
{ |
|||
return Matches(value, @"\d+"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检测指定字符串中是否包含数字
|
|||
/// </summary>
|
|||
public static bool IsMatchNumber(this string value) |
|||
{ |
|||
return IsMatch(value, @"\d"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检测指定字符串是否全部为数字并且长度等于指定长度
|
|||
/// </summary>
|
|||
public static bool IsMatchNumber(this string value, int length) |
|||
{ |
|||
var regex = new Regex(@"^\d{" + length + "}$"); |
|||
return regex.IsMatch(value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 截取指定字符串之间的字符串
|
|||
/// </summary>
|
|||
/// <param name="source"></param>
|
|||
/// <param name="startString">起始字符串</param>
|
|||
/// <param name="endStrings">结束字符串,可多个</param>
|
|||
/// <returns>返回的中间字符串</returns>
|
|||
public static string Substring(this string source, string startString, params string[] endStrings) |
|||
{ |
|||
if (source.IsMissing()) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
var startIndex = 0; |
|||
if (!string.IsNullOrEmpty(startString)) |
|||
{ |
|||
startIndex = source.IndexOf(startString, StringComparison.OrdinalIgnoreCase); |
|||
if (startIndex < 0) |
|||
{ |
|||
throw new InvalidOperationException($"在源字符串中无法找到“{startString}”的子串位置"); |
|||
} |
|||
|
|||
startIndex += startString.Length; |
|||
} |
|||
|
|||
var endIndex = source.Length; |
|||
endStrings = endStrings.OrderByDescending(m => m.Length).ToArray(); |
|||
foreach (var endString in endStrings) |
|||
{ |
|||
if (string.IsNullOrEmpty(endString)) |
|||
{ |
|||
endIndex = source.Length; |
|||
break; |
|||
} |
|||
|
|||
endIndex = source.IndexOf(endString, startIndex, StringComparison.OrdinalIgnoreCase); |
|||
if (endIndex < 0 || endIndex < startIndex) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
break; |
|||
} |
|||
|
|||
if (endIndex < 0 || endIndex < startIndex) |
|||
{ |
|||
throw new InvalidOperationException($"在源字符串中无法找到“{endStrings.ExpandAndToString()}”的子串位置"); |
|||
} |
|||
|
|||
var length = endIndex - startIndex; |
|||
|
|||
return source.Substring(startIndex, length); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 用正则表达式截取字符串
|
|||
/// </summary>
|
|||
public static string Substring2(this string source, string startString, string endString) |
|||
{ |
|||
return source.Substring2(startString, endString, false); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 用正则表达式截取字符串
|
|||
/// </summary>
|
|||
public static string Substring2(this string source, string startString, string endString, bool containsEmpty) |
|||
{ |
|||
if (source.IsMissing()) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
var inner = containsEmpty ? "\\s\\S" : "\\S"; |
|||
var result = source.Match($"(?<={startString})([{inner}]+?)(?={endString})"); |
|||
return result.IsMissing() ? null : result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否电子邮件
|
|||
/// </summary>
|
|||
public static bool IsEmail(this string value) |
|||
{ |
|||
const string pattern = @"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"; |
|||
return value.IsMatch(pattern); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否是IP地址
|
|||
/// </summary>
|
|||
public static bool IsIpAddress(this string value) |
|||
{ |
|||
const string pattern = |
|||
@"^((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))$"; |
|||
return value.IsMatch(pattern); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否是整数
|
|||
/// </summary>
|
|||
public static bool IsNumeric(this string value) |
|||
{ |
|||
const string pattern = @"^\-?[0-9]+$"; |
|||
return value.IsMatch(pattern); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否是Unicode字符串
|
|||
/// </summary>
|
|||
public static bool IsUnicode(this string value) |
|||
{ |
|||
const string pattern = @"^[\u4E00-\u9FA5\uE815-\uFA29]+$"; |
|||
return value.IsMatch(pattern); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否Url字符串
|
|||
/// </summary>
|
|||
public static bool IsUrl(this string value) |
|||
{ |
|||
try |
|||
{ |
|||
if (string.IsNullOrEmpty(value) || value.Contains(' ')) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
var uri = new Uri(value); |
|||
return true; |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否身份证号,验证如下3种情况:
|
|||
/// 1.身份证号码为15位数字;
|
|||
/// 2.身份证号码为18位数字;
|
|||
/// 3.身份证号码为17位数字+1个字母
|
|||
/// </summary>
|
|||
public static bool IsIdentityCardId(this string value) |
|||
{ |
|||
if (value.Length != 15 && value.Length != 18) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
Regex regex; |
|||
string[] array; |
|||
if (value.Length == 15) |
|||
{ |
|||
regex = new Regex(@"^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})_"); |
|||
if (!regex.Match(value).Success) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
array = regex.Split(value); |
|||
return DateTime.TryParse(string.Format("{0}-{1}-{2}", "19" + array[2], array[3], array[4]), out _); |
|||
} |
|||
|
|||
regex = new Regex(@"^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9Xx])$"); |
|||
if (!regex.Match(value).Success) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
array = regex.Split(value); |
|||
if (!DateTime.TryParse(string.Format("{0}-{1}-{2}", array[2], array[3], array[4]), out _)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
//校验最后一位
|
|||
var chars = value.ToCharArray().Select(m => m.ToString()).ToArray(); |
|||
int[] weights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; |
|||
var sum = 0; |
|||
for (var i = 0; i < 17; i++) |
|||
{ |
|||
var num = int.Parse(chars[i]); |
|||
sum += num * weights[i]; |
|||
} |
|||
|
|||
var mod = sum % 11; |
|||
var vCode = "10X98765432"; // 检验码字符串
|
|||
var last = vCode.ToCharArray().ElementAt(mod).ToString(); |
|||
return chars.Last().ToUpper() == last; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否手机号码
|
|||
/// </summary>
|
|||
/// <param name="value"></param>
|
|||
/// <param name="isRestrict">是否按严格格式验证</param>
|
|||
public static bool IsMobileNumber(this string value, bool isRestrict = false) |
|||
{ |
|||
var pattern = isRestrict ? @"^[1][3-8]\d{9}$" : @"^[1]\d{10}$"; |
|||
return value.IsMatch(pattern); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region 其他操作
|
|||
|
|||
/// <summary>
|
|||
/// 判断指定的字符串不是 null、空。
|
|||
/// </summary>
|
|||
public static bool IsNotNullOrEmpty(this string str) |
|||
{ |
|||
return !string.IsNullOrEmpty(str); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 判断指定的字符串不是 null、空或者仅由空白字符组成
|
|||
/// </summary>
|
|||
public static bool IsNotNullOrWhiteSpace(this string str) |
|||
{ |
|||
return !string.IsNullOrWhiteSpace(str); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 指示指定的字符串是 null、空或者仅由空白字符组成
|
|||
/// </summary>
|
|||
public static bool IsMissing(this string value) |
|||
{ |
|||
return string.IsNullOrWhiteSpace(value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 为指定格式的字符串填充相应对象来生成字符串
|
|||
/// </summary>
|
|||
/// <param name="format">字符串格式,占位符以{n}表示</param>
|
|||
/// <param name="args">用于填充占位符的参数</param>
|
|||
/// <returns>格式化后的字符串</returns>
|
|||
public static string FormatWith(this string format, params object[] args) |
|||
{ |
|||
Guard.NotNull(format, nameof(format)); |
|||
return string.Format(CultureInfo.CurrentCulture, format, args); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将字符串反转
|
|||
/// </summary>
|
|||
/// <param name="value">要反转的字符串</param>
|
|||
public static string ReverseString(this string value) |
|||
{ |
|||
Guard.NotNull(value, nameof(value)); |
|||
return new string(value.Reverse().ToArray()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 单词复数变成单数形式
|
|||
/// </summary>
|
|||
/// <param name="word"></param>
|
|||
/// <returns></returns>
|
|||
public static string ToSingular(this string word) |
|||
{ |
|||
var plural1 = new Regex("(?<keep>[^aeiou])ies$"); |
|||
var plural2 = new Regex("(?<keep>[aeiou]y)s$"); |
|||
var plural3 = new Regex("(?<keep>[sxzh])es$"); |
|||
var plural4 = new Regex("(?<keep>[^sxzhyu])s$"); |
|||
|
|||
if (plural1.IsMatch(word)) |
|||
{ |
|||
return plural1.Replace(word, "${keep}y"); |
|||
} |
|||
|
|||
if (plural2.IsMatch(word)) |
|||
{ |
|||
return plural2.Replace(word, "${keep}"); |
|||
} |
|||
|
|||
if (plural3.IsMatch(word)) |
|||
{ |
|||
return plural3.Replace(word, "${keep}"); |
|||
} |
|||
|
|||
if (plural4.IsMatch(word)) |
|||
{ |
|||
return plural4.Replace(word, "${keep}"); |
|||
} |
|||
|
|||
return word; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 单词单数变成复数形式
|
|||
/// </summary>
|
|||
/// <param name="word"></param>
|
|||
/// <returns></returns>
|
|||
public static string ToPlural(this string word) |
|||
{ |
|||
var plural1 = new Regex("(?<keep>[^aeiou])y$"); |
|||
var plural2 = new Regex("(?<keep>[aeiou]y)$"); |
|||
var plural3 = new Regex("(?<keep>[sxzh])$"); |
|||
var plural4 = new Regex("(?<keep>[^sxzhy])$"); |
|||
|
|||
if (plural1.IsMatch(word)) |
|||
{ |
|||
return plural1.Replace(word, "${keep}ies"); |
|||
} |
|||
|
|||
if (plural2.IsMatch(word)) |
|||
{ |
|||
return plural2.Replace(word, "${keep}s"); |
|||
} |
|||
|
|||
if (plural3.IsMatch(word)) |
|||
{ |
|||
return plural3.Replace(word, "${keep}es"); |
|||
} |
|||
|
|||
if (plural4.IsMatch(word)) |
|||
{ |
|||
return plural4.Replace(word, "${keep}s"); |
|||
} |
|||
|
|||
return word; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 以指定字符串作为分隔符将指定字符串分隔成数组
|
|||
/// </summary>
|
|||
/// <param name="value">要分割的字符串</param>
|
|||
/// <param name="strSplit">字符串类型的分隔符</param>
|
|||
/// <param name="removeEmptyEntries">是否移除数据中元素为空字符串的项</param>
|
|||
/// <returns>分割后的数据</returns>
|
|||
public static string[] Split(this string value, string strSplit, bool removeEmptyEntries = false) |
|||
{ |
|||
return value.Split(new[] {strSplit}, |
|||
removeEmptyEntries ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 支持汉字的字符串长度,汉字长度计为2
|
|||
/// </summary>
|
|||
/// <param name="value">参数字符串</param>
|
|||
/// <returns>当前字符串的长度,汉字长度为2</returns>
|
|||
public static int TextLength(this string value) |
|||
{ |
|||
var ascii = new ASCIIEncoding(); |
|||
var tempLen = 0; |
|||
var bytes = ascii.GetBytes(value); |
|||
foreach (var b in bytes) |
|||
{ |
|||
if (b == 63) |
|||
{ |
|||
tempLen += 2; |
|||
} |
|||
else |
|||
{ |
|||
tempLen += 1; |
|||
} |
|||
} |
|||
|
|||
return tempLen; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将JSON字符串还原为对象
|
|||
/// </summary>
|
|||
/// <typeparam name="T">要转换的目标类型</typeparam>
|
|||
/// <param name="json">JSON字符串</param>
|
|||
/// <returns></returns>
|
|||
public static T FromJsonString<T>(this string json) |
|||
{ |
|||
Guard.NotNull(json, nameof(json)); |
|||
return JsonConvert.DeserializeObject<T>(json); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将JSON字符串还原为对象
|
|||
/// </summary>
|
|||
/// <param name="json">JSON字符串 </param>
|
|||
/// <param name="type">数据类型</param>
|
|||
public static object FromJsonString(this string json, Type type) |
|||
{ |
|||
return JsonConvert.DeserializeObject(json, type); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 给URL添加查询参数
|
|||
/// </summary>
|
|||
/// <param name="url">URL字符串</param>
|
|||
/// <param name="queries">要添加的参数,形如:"id=1,cid=2"</param>
|
|||
/// <returns></returns>
|
|||
public static string AddUrlQuery(this string url, params string[] queries) |
|||
{ |
|||
foreach (var query in queries) |
|||
{ |
|||
if (!url.Contains("?")) |
|||
{ |
|||
url += "?"; |
|||
} |
|||
else if (!url.EndsWith("&")) |
|||
{ |
|||
url += "&"; |
|||
} |
|||
|
|||
url += query; |
|||
} |
|||
|
|||
return url; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取URL中指定参数的值,不存在返回空字符串
|
|||
/// </summary>
|
|||
public static string GetUrlQuery(this string url, string key) |
|||
{ |
|||
var uri = new Uri(url); |
|||
var query = uri.Query; |
|||
if (string.IsNullOrEmpty(query)) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
query = query.TrimStart('?'); |
|||
var dict = (from m in query.Split("&", true) |
|||
let strs = m.Split("=") |
|||
select new KeyValuePair<string, string>(strs[0], strs[1])) |
|||
.ToDictionary(m => m.Key, m => m.Value); |
|||
if (dict.ContainsKey(key)) |
|||
{ |
|||
return dict[key]; |
|||
} |
|||
|
|||
return string.Empty; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 给URL添加 # 参数
|
|||
/// </summary>
|
|||
/// <param name="url">URL字符串</param>
|
|||
/// <param name="query">要添加的参数</param>
|
|||
/// <returns></returns>
|
|||
public static string AddHashFragment(this string url, string query) |
|||
{ |
|||
Guard.NotNull(url, nameof(url)); |
|||
Guard.NotNull(query, nameof(query)); |
|||
|
|||
if (!url.Contains("#")) |
|||
{ |
|||
url += "#"; |
|||
} |
|||
|
|||
return url + query; |
|||
} |
|||
|
|||
|
|||
|
|||
/// <summary>
|
|||
/// 将<see cref="byte"/>[]数组转换为Base64字符串
|
|||
/// </summary>
|
|||
public static string ToBase64String(this byte[] bytes) |
|||
{ |
|||
Guard.NotNull(bytes, nameof(bytes)); |
|||
|
|||
return Convert.ToBase64String(bytes); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将字符串转换为Base64字符串,默认编码为<see cref="Encoding.UTF8"/>
|
|||
/// </summary>
|
|||
/// <param name="source">正常的字符串</param>
|
|||
/// <param name="encoding">编码</param>
|
|||
/// <returns>Base64字符串</returns>
|
|||
public static string ToBase64String(this string source, Encoding encoding = null) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
|
|||
if (encoding == null) encoding = Encoding.UTF8; |
|||
|
|||
return Convert.ToBase64String(encoding.GetBytes(source)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将Base64字符串转换为正常字符串,默认编码为<see cref="Encoding.UTF8"/>
|
|||
/// </summary>
|
|||
/// <param name="base64String">Base64字符串</param>
|
|||
/// <param name="encoding">编码</param>
|
|||
/// <returns>正常字符串</returns>
|
|||
public static string FromBase64String(this string base64String, Encoding encoding = null) |
|||
{ |
|||
Guard.NotNull(base64String, nameof(base64String)); |
|||
|
|||
if (encoding == null) encoding = Encoding.UTF8; |
|||
|
|||
var bytes = Convert.FromBase64String(base64String); |
|||
return encoding.GetString(bytes); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将字符串进行UrlDecode解码
|
|||
/// </summary>
|
|||
/// <param name="source">待UrlDecode解码的字符串</param>
|
|||
/// <returns>UrlDecode解码后的字符串</returns>
|
|||
public static string ToUrlDecode(this string source) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
|
|||
return HttpUtility.UrlDecode(source); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将字符串进行UrlEncode编码
|
|||
/// </summary>
|
|||
/// <param name="source">待UrlEncode编码的字符串</param>
|
|||
/// <returns>UrlEncode编码后的字符串</returns>
|
|||
public static string ToUrlEncode(this string source) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
|
|||
return HttpUtility.UrlEncode(source); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将字符串进行HtmlDecode解码
|
|||
/// </summary>
|
|||
/// <param name="source">待HtmlDecode解码的字符串</param>
|
|||
/// <returns>HtmlDecode解码后的字符串</returns>
|
|||
public static string ToHtmlDecode(this string source) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
|
|||
return HttpUtility.HtmlDecode(source); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将字符串进行HtmlEncode编码
|
|||
/// </summary>
|
|||
/// <param name="source">待HtmlEncode编码的字符串</param>
|
|||
/// <returns>HtmlEncode编码后的字符串</returns>
|
|||
public static string ToHtmlEncode(this string source) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
|
|||
return HttpUtility.HtmlEncode(source); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将字符串转换为十六进制字符串,默认编码为<see cref="Encoding.UTF8"/>
|
|||
/// </summary>
|
|||
public static string ToHexString(this string source, Encoding encoding = null) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
|
|||
if (encoding == null) encoding = Encoding.UTF8; |
|||
|
|||
byte[] bytes = encoding.GetBytes(source); |
|||
return bytes.ToHexString(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将十六进制字符串转换为常规字符串,默认编码为<see cref="Encoding.UTF8"/>
|
|||
/// </summary>
|
|||
public static string FromHexString(this string hexString, Encoding encoding = null) |
|||
{ |
|||
Guard.NotNull(hexString, nameof(hexString)); |
|||
|
|||
if (encoding == null) encoding = Encoding.UTF8; |
|||
|
|||
var bytes = hexString.ToHexBytes(); |
|||
return encoding.GetString(bytes); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将byte[]编码为十六进制字符串
|
|||
/// </summary>
|
|||
/// <param name="bytes">byte[]数组</param>
|
|||
/// <returns>十六进制字符串</returns>
|
|||
public static string ToHexString(this byte[] bytes) |
|||
{ |
|||
Guard.NotNull(bytes, nameof(bytes)); |
|||
|
|||
return bytes.Aggregate(string.Empty, (current, t) => current + t.ToString("X2")); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将十六进制字符串转换为byte[]
|
|||
/// </summary>
|
|||
/// <param name="hexString">十六进制字符串</param>
|
|||
/// <returns>byte[]数组</returns>
|
|||
public static byte[] ToHexBytes(this string hexString) |
|||
{ |
|||
hexString = hexString ?? ""; |
|||
hexString = hexString.Replace(" ", ""); |
|||
byte[] bytes = new byte[hexString.Length / 2]; |
|||
for (int i = 0; i < bytes.Length; i++) |
|||
{ |
|||
bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); |
|||
} |
|||
|
|||
return bytes; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将字符串进行Unicode编码,变成形如“\u7f16\u7801”的形式
|
|||
/// </summary>
|
|||
/// <param name="source">要进行编号的字符串</param>
|
|||
public static string ToUnicodeString(this string source) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
|
|||
var regex = new Regex(@"[^\u0000-\u00ff]"); |
|||
return regex.Replace(source, m => string.Format(@"\u{0:x4}", (short) m.Value[0])); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将形如“\u7f16\u7801”的Unicode字符串解码
|
|||
/// </summary>
|
|||
public static string FromUnicodeString(this string source) |
|||
{ |
|||
var regex = new Regex(@"\\u([0-9a-fA-F]{4})", RegexOptions.Compiled); |
|||
return regex.Replace(source, |
|||
m => |
|||
{ |
|||
short s; |
|||
if (short.TryParse(m.Groups[1].Value, NumberStyles.HexNumber, CultureInfo.InstalledUICulture, |
|||
out s)) |
|||
{ |
|||
return "" + (char) s; |
|||
} |
|||
|
|||
return m.Value; |
|||
}); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将驼峰字符串按单词拆分并转换成小写,再以特定字符串分隔
|
|||
/// </summary>
|
|||
/// <param name="str">待转换的字符串</param>
|
|||
/// <param name="splitStr">分隔符字符</param>
|
|||
/// <returns></returns>
|
|||
public static string UpperToLowerAndSplit(this string str, string splitStr = "-") |
|||
{ |
|||
if (string.IsNullOrEmpty(str)) |
|||
{ |
|||
return str; |
|||
} |
|||
|
|||
List<string> words = new List<string>(); |
|||
while (str.Length > 0) |
|||
{ |
|||
char c = str.FirstOrDefault(char.IsUpper); |
|||
if (c == default(char)) |
|||
{ |
|||
words.Add(str); |
|||
break; |
|||
} |
|||
|
|||
int upperIndex = str.IndexOf(c); |
|||
if (upperIndex < 0) //admin
|
|||
{ |
|||
return str; |
|||
} |
|||
|
|||
if (upperIndex > 0) //adminAdmin
|
|||
{ |
|||
string first = str.Substring(0, upperIndex); |
|||
words.Add(first); |
|||
str = str.Substring(upperIndex, str.Length - upperIndex); |
|||
continue; |
|||
} |
|||
|
|||
str = char.ToLower(str[0]) + str.Substring(1, str.Length - 1); |
|||
} |
|||
|
|||
return words.ExpandAndToString(splitStr); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将驼峰字符串的第一个字符小写
|
|||
/// </summary>
|
|||
public static string LowerFirstChar(this string str) |
|||
{ |
|||
if (string.IsNullOrEmpty(str) || !char.IsUpper(str[0])) |
|||
{ |
|||
return str; |
|||
} |
|||
|
|||
if (str.Length == 1) |
|||
{ |
|||
return char.ToLower(str[0]).ToString(); |
|||
} |
|||
|
|||
return char.ToLower(str[0]) + str.Substring(1, str.Length - 1); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 将小驼峰字符串的第一个字符大写
|
|||
/// </summary>
|
|||
public static string UpperFirstChar(this string str) |
|||
{ |
|||
if (string.IsNullOrEmpty(str) || !char.IsLower(str[0])) |
|||
{ |
|||
return str; |
|||
} |
|||
|
|||
if (str.Length == 1) |
|||
{ |
|||
return char.ToUpper(str[0]).ToString(); |
|||
} |
|||
|
|||
return char.ToUpper(str[0]) + str.Substring(1, str.Length - 1); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 计算当前字符串与指定字符串的编辑距离(相似度)
|
|||
/// </summary>
|
|||
/// <param name="source">源字符串</param>
|
|||
/// <param name="target">目标字符串</param>
|
|||
/// <param name="similarity">输出相似度</param>
|
|||
/// <param name="ignoreCase">是否忽略大小写</param>
|
|||
/// <returns>编辑距离</returns>
|
|||
public static int LevenshteinDistance(this string source, string target, out double similarity, |
|||
bool ignoreCase = false) |
|||
{ |
|||
if (string.IsNullOrEmpty(source)) |
|||
{ |
|||
if (string.IsNullOrEmpty(target)) |
|||
{ |
|||
similarity = 1; |
|||
return 0; |
|||
} |
|||
|
|||
similarity = 0; |
|||
return target.Length; |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(target)) |
|||
{ |
|||
similarity = 0; |
|||
return source.Length; |
|||
} |
|||
|
|||
string from, to; |
|||
if (ignoreCase) |
|||
{ |
|||
from = source; |
|||
to = target; |
|||
} |
|||
else |
|||
{ |
|||
from = source.ToLower(); |
|||
to = source.ToLower(); |
|||
} |
|||
|
|||
int m = from.Length, n = to.Length; |
|||
int[,] mn = new int[m + 1, n + 1]; |
|||
for (int i = 0; i <= m; i++) |
|||
{ |
|||
mn[i, 0] = i; |
|||
} |
|||
|
|||
for (int j = 1; j <= n; j++) |
|||
{ |
|||
mn[0, j] = j; |
|||
} |
|||
|
|||
for (int i = 1; i <= m; i++) |
|||
{ |
|||
char c = from[i - 1]; |
|||
for (int j = 1; j <= n; j++) |
|||
{ |
|||
if (c == to[j - 1]) |
|||
{ |
|||
mn[i, j] = mn[i - 1, j - 1]; |
|||
} |
|||
else |
|||
{ |
|||
mn[i, j] = Math.Min(mn[i - 1, j - 1], Math.Min(mn[i - 1, j], mn[i, j - 1])) + 1; |
|||
} |
|||
} |
|||
} |
|||
|
|||
int maxLength = Math.Max(m, n); |
|||
similarity = (double) (maxLength - mn[m, n]) / maxLength; |
|||
return mn[m, n]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 计算两个字符串的相似度,应用公式:相似度=kq*q/(kq*q+kr*r+ks*s)(kq>0,kr>=0,ka>=0)
|
|||
/// 其中,q是字符串1和字符串2中都存在的单词的总数,s是字符串1中存在,字符串2中不存在的单词总数,r是字符串2中存在,字符串1中不存在的单词总数. kq,kr和ka分别是q,r,s的权重,根据实际的计算情况,我们设kq=2,kr=ks=1.
|
|||
/// </summary>
|
|||
/// <param name="source">源字符串</param>
|
|||
/// <param name="target">目标字符串</param>
|
|||
/// <param name="ignoreCase">是否忽略大小写</param>
|
|||
/// <returns>字符串相似度</returns>
|
|||
public static double GetSimilarityWith(this string source, string target, bool ignoreCase = false) |
|||
{ |
|||
if (string.IsNullOrEmpty(source) && string.IsNullOrEmpty(target)) |
|||
{ |
|||
return 1; |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(target)) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
const double kq = 2, kr = 1, ks = 1; |
|||
char[] sourceChars = source.ToCharArray(), targetChars = target.ToCharArray(); |
|||
|
|||
//获取交集数量
|
|||
int q = sourceChars.Intersect(targetChars).Count(), s = sourceChars.Length - q, r = targetChars.Length - q; |
|||
return kq * q / (kq * q + kr * r + ks * s); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 标准化Path字符串,将 \\ 转换为 /
|
|||
/// </summary>
|
|||
/// <param name="path">Path字符串</param>
|
|||
public static string NormalizePath(this string path) |
|||
{ |
|||
return path.Replace('\\', '/'); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// (Pascal) 命名法 的字符串 改为 短横线分隔式命名
|
|||
/// 例如UserName => user-name
|
|||
/// </summary>
|
|||
public static string PascalToKebabCase(this string value) |
|||
{ |
|||
if (string.IsNullOrEmpty(value)) |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
return Regex.Replace( |
|||
value, |
|||
"(?<!^)([A-Z][a-z]|(?<=[a-z])[A-Z])", |
|||
"-$1", |
|||
RegexOptions.Compiled) |
|||
.Trim() |
|||
.ToLower(); |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -0,0 +1,241 @@ |
|||
using Lion.Abp.Extension; |
|||
using System.Linq; |
|||
|
|||
namespace System.Text |
|||
{ |
|||
/// <summary>
|
|||
/// StringBuilder 扩展方法类
|
|||
/// </summary>
|
|||
public static class StringBuilderExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 去除<seealso cref="StringBuilder"/>开头的空格
|
|||
/// </summary>
|
|||
/// <param name="stringBuilder"></param>
|
|||
/// <returns>返回修改后的StringBuilder,主要用于链式操作</returns>
|
|||
public static StringBuilder TrimStart(this StringBuilder stringBuilder) |
|||
{ |
|||
Guard.NotNull(stringBuilder, nameof(stringBuilder)); |
|||
|
|||
return stringBuilder.TrimStart(' '); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 去除<seealso cref="StringBuilder"/>开头的指定<seealso cref="char"/>
|
|||
/// </summary>
|
|||
/// <param name="stringBuilder"></param>
|
|||
/// <param name="c">要去掉的<seealso cref="char"/></param>
|
|||
/// <returns></returns>
|
|||
public static StringBuilder TrimStart(this StringBuilder stringBuilder, char c) |
|||
{ |
|||
Guard.NotNull(stringBuilder, nameof(stringBuilder)); |
|||
|
|||
if (stringBuilder.Length == 0) |
|||
return stringBuilder; |
|||
while (c.Equals(stringBuilder[0])) |
|||
{ |
|||
stringBuilder.Remove(0, 1); |
|||
} |
|||
|
|||
return stringBuilder; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 去除<seealso cref="StringBuilder"/>开头的指定字符数组
|
|||
/// </summary>
|
|||
/// <param name="stringBuilder"></param>
|
|||
/// <param name="chars">要去掉的字符数组</param>
|
|||
/// <returns></returns>
|
|||
public static StringBuilder TrimStart(this StringBuilder stringBuilder, char[] chars) |
|||
{ |
|||
Guard.NotNull(stringBuilder, nameof(stringBuilder)); |
|||
Guard.NotNull(chars, nameof(chars)); |
|||
|
|||
return stringBuilder.TrimStart(new string(chars)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 去除<see cref="StringBuilder"/>开头的指定的<seealso cref="string"/>
|
|||
/// </summary>
|
|||
/// <param name="stringBuilder"></param>
|
|||
/// <param name="str">要去掉的<seealso cref="string"/></param>
|
|||
/// <returns></returns>
|
|||
public static StringBuilder TrimStart(this StringBuilder stringBuilder, string str) |
|||
{ |
|||
Guard.NotNull(stringBuilder, nameof(stringBuilder)); |
|||
|
|||
if (string.IsNullOrEmpty(str) |
|||
|| stringBuilder.Length == 0 |
|||
|| str.Length > stringBuilder.Length) |
|||
{ |
|||
return stringBuilder; |
|||
} |
|||
|
|||
while (stringBuilder.SubString(0, str.Length).Equals(str)) |
|||
{ |
|||
stringBuilder.Remove(0, str.Length); |
|||
if (str.Length > stringBuilder.Length) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return stringBuilder; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 去除StringBuilder结尾的空格
|
|||
/// </summary>
|
|||
/// <param name="stringBuilder">StringBuilder</param>
|
|||
/// <returns>返回修改后的StringBuilder,主要用于链式操作</returns>
|
|||
public static StringBuilder TrimEnd(this StringBuilder stringBuilder) |
|||
{ |
|||
return stringBuilder.TrimEnd(' '); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 去除<see cref="StringBuilder"/>结尾指定字符
|
|||
/// </summary>
|
|||
/// <param name="stringBuilder"></param>
|
|||
/// <param name="c">要去掉的字符</param>
|
|||
/// <returns></returns>
|
|||
public static StringBuilder TrimEnd(this StringBuilder stringBuilder, char c) |
|||
{ |
|||
Guard.NotNull(stringBuilder, nameof(stringBuilder)); |
|||
if (stringBuilder.Length == 0) |
|||
{ |
|||
return stringBuilder; |
|||
} |
|||
|
|||
while (c.Equals(stringBuilder[stringBuilder.Length - 1])) |
|||
{ |
|||
stringBuilder.Remove(stringBuilder.Length - 1, 1); |
|||
} |
|||
|
|||
return stringBuilder; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 去除<see cref="StringBuilder"/>结尾指定字符数组
|
|||
/// </summary>
|
|||
/// <param name="stringBuilder"></param>
|
|||
/// <param name="chars">要去除的字符数组</param>
|
|||
/// <returns></returns>
|
|||
public static StringBuilder TrimEnd(this StringBuilder stringBuilder, char[] chars) |
|||
{ |
|||
Guard.NotNull(stringBuilder, nameof(stringBuilder)); |
|||
Guard.NotNull(chars, nameof(chars)); |
|||
|
|||
return stringBuilder.TrimEnd(new string(chars)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 去除<see cref="StringBuilder"/>结尾指定字符串
|
|||
/// </summary>
|
|||
/// <param name="stringBuilder"></param>
|
|||
/// <param name="str">要去除的字符串</param>
|
|||
/// <returns></returns>
|
|||
public static StringBuilder TrimEnd(this StringBuilder stringBuilder, string str) |
|||
{ |
|||
Guard.NotNull(stringBuilder, nameof(stringBuilder)); |
|||
if (string.IsNullOrEmpty(str) |
|||
|| stringBuilder.Length == 0 |
|||
|| str.Length > stringBuilder.Length) |
|||
{ |
|||
return stringBuilder; |
|||
} |
|||
while (stringBuilder.SubString(stringBuilder.Length - str.Length, str.Length).Equals(str)) |
|||
{ |
|||
stringBuilder.Remove(stringBuilder.Length - str.Length, str.Length); |
|||
if (stringBuilder.Length < str.Length) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return stringBuilder; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 去除StringBuilder两端的空格
|
|||
/// </summary>
|
|||
/// <param name="stringBuilder">StringBuilder</param>
|
|||
/// <returns>返回修改后的StringBuilder,主要用于链式操作</returns>
|
|||
public static StringBuilder Trim(this StringBuilder stringBuilder) |
|||
{ |
|||
Guard.NotNull(stringBuilder, nameof(stringBuilder)); |
|||
|
|||
if (stringBuilder.Length == 0) |
|||
return stringBuilder; |
|||
return stringBuilder.TrimEnd().TrimStart(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 返回<see cref="StringBuilder"/>从起始位置指定长度的字符串
|
|||
/// </summary>
|
|||
/// <param name="stringBuilder"></param>
|
|||
/// <param name="start">起始位置</param>
|
|||
/// <param name="length">长度</param>
|
|||
/// <returns>字符串</returns>
|
|||
/// <exception cref="IndexOutOfRangeException">超出字符串索引长度异常</exception>
|
|||
public static string SubString(this StringBuilder stringBuilder, int start, int length) |
|||
{ |
|||
Guard.NotNull(stringBuilder, nameof(stringBuilder)); |
|||
|
|||
if (start + length > stringBuilder.Length) |
|||
{ |
|||
throw new IndexOutOfRangeException("超出字符串索引长度"); |
|||
} |
|||
|
|||
var cs = new char[length]; |
|||
for (var i = 0; i < length; i++) |
|||
{ |
|||
cs[i] = stringBuilder[start + i]; |
|||
} |
|||
|
|||
return new string(cs); |
|||
} |
|||
|
|||
public static StringBuilder AppendLineWithControlChar(this StringBuilder stringBuilder, StringBuilder sb, string newLine) |
|||
{ |
|||
stringBuilder = AppendWithControlChar(stringBuilder, sb.ToString()); |
|||
return stringBuilder.Append(newLine); |
|||
} |
|||
|
|||
public static StringBuilder AppendLineWithControlChar(this StringBuilder stringBuilder, string str, string newLine) |
|||
{ |
|||
stringBuilder = AppendWithControlChar(stringBuilder, str); |
|||
return stringBuilder.Append(newLine); |
|||
} |
|||
|
|||
public static StringBuilder AppendWithControlChar(this StringBuilder stringBuilder, StringBuilder sb) |
|||
{ |
|||
return AppendWithControlChar(stringBuilder, sb.ToString()); |
|||
} |
|||
|
|||
public static StringBuilder AppendWithControlChar(this StringBuilder stringBuilder, string str) |
|||
{ |
|||
if (str.Contains('\b')) |
|||
{ |
|||
foreach (var c in str) |
|||
{ |
|||
if (c == '\b') |
|||
{ |
|||
stringBuilder.Length--; |
|||
} |
|||
else |
|||
{ |
|||
stringBuilder.Append(c); |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
stringBuilder.Append(str); |
|||
} |
|||
|
|||
return stringBuilder; |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net5.0</TargetFramework> |
|||
</PropertyGroup> |
|||
|
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\shared\CompanyName.ProjectName.Shared.Hosting.Gateways\CompanyName.ProjectName.Shared.Hosting.Gateways.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,24 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace CompanyName.ProjectName.WebGateway |
|||
{ |
|||
public class Program |
|||
{ |
|||
public static void Main(string[] args) |
|||
{ |
|||
CreateHostBuilder(args).Build().Run(); |
|||
} |
|||
|
|||
public static IHostBuilder CreateHostBuilder(string[] args) => |
|||
Host.CreateDefaultBuilder(args) |
|||
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }) |
|||
.UseAutofac(); |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
{ |
|||
"$schema": "http://json.schemastore.org/launchsettings.json", |
|||
"profiles": { |
|||
"CompanyName.ProjectName.WebGateway": { |
|||
"commandName": "Project", |
|||
"launchBrowser": false, |
|||
"launchUrl": "swagger", |
|||
"applicationUrl": "http://localhost:44314", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.AspNetCore.HttpsPolicy; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.OpenApi.Models; |
|||
|
|||
namespace CompanyName.ProjectName.WebGateway |
|||
{ |
|||
public class Startup |
|||
{ |
|||
public void ConfigureServices(IServiceCollection services) |
|||
{ |
|||
services.AddApplication<WebGatewayModule>(); |
|||
} |
|||
|
|||
public void Configure(IApplicationBuilder app) |
|||
{ |
|||
app.InitializeApplication(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using CompanyName.ProjectName.Shared.Hosting.Gateways; |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Cors; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.OpenApi.Models; |
|||
using Ocelot.Middleware; |
|||
using Swashbuckle.AspNetCore.SwaggerUI; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace CompanyName.ProjectName.WebGateway |
|||
{ |
|||
[DependsOn( |
|||
typeof(SharedHostingGatewayModule))] |
|||
public class WebGatewayModule : AbpModule |
|||
{ |
|||
private const string DefaultCorsPolicyName = "Default"; |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
ConfigureCors(context); |
|||
ConfigureSwaggerServices(context); |
|||
} |
|||
|
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var app = context.GetApplicationBuilder(); |
|||
var env = context.GetEnvironment(); |
|||
app.UseCorrelationId(); |
|||
app.UseCors(DefaultCorsPolicyName); |
|||
app.UseRouting(); |
|||
app.UseSwagger(); |
|||
app.UseSwaggerUI(options => |
|||
{ |
|||
options.SwaggerEndpoint("/ProjectName/swagger.json", "ProjectNameAPI"); |
|||
options.DefaultModelsExpandDepth(-1); |
|||
options.DocExpansion(DocExpansion.None); |
|||
}); |
|||
|
|||
app.UseConfiguredEndpoints(); |
|||
app.UseWebSockets(); |
|||
app.UseOcelot().Wait(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 配置跨域
|
|||
/// </summary>
|
|||
/// <param name="context"></param>
|
|||
private void ConfigureCors(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
context.Services.AddCors(options => |
|||
{ |
|||
options.AddPolicy(DefaultCorsPolicyName, builder => |
|||
{ |
|||
builder |
|||
.WithOrigins( |
|||
configuration["App:CorsOrigins"] |
|||
.Split(",", StringSplitOptions.RemoveEmptyEntries) |
|||
.Select(o => o.RemovePostFix("/")) |
|||
.ToArray() |
|||
) |
|||
.WithAbpExposedHeaders() |
|||
.SetIsOriginAllowedToAllowWildcardSubdomains() |
|||
.AllowAnyHeader() |
|||
.AllowAnyMethod() |
|||
.AllowCredentials(); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
private static void ConfigureSwaggerServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddSwaggerGen( |
|||
options => |
|||
{ |
|||
options.SwaggerDoc("v1", new OpenApiInfo {Title = "WebGateway API", Version = "v1"}); |
|||
options.DocInclusionPredicate((docName, description) => true); |
|||
options.AddSecurityRequirement(new OpenApiSecurityRequirement |
|||
{ |
|||
{ |
|||
new OpenApiSecurityScheme |
|||
{ |
|||
Reference = new OpenApiReference |
|||
{ |
|||
Type = ReferenceType.SecurityScheme, Id = "Bearer" |
|||
} |
|||
}, |
|||
new List<string>() |
|||
} |
|||
}); |
|||
|
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
{ |
|||
"Logging": { |
|||
"LogLevel": { |
|||
"Default": "Information", |
|||
"Microsoft": "Warning", |
|||
"Microsoft.Hosting.Lifetime": "Information" |
|||
} |
|||
}, |
|||
"AllowedHosts": "*", |
|||
"App": { |
|||
"SelfUrl": "http://localhost:44314", |
|||
"CorsOrigins": "http://localhost:4200" |
|||
}, |
|||
"GlobalConfiguration": { |
|||
}, |
|||
"Routes": [ |
|||
{ |
|||
"DownstreamPathTemplate": "/swagger/ProjectName/swagger.json", |
|||
"DownstreamScheme": "http", |
|||
"ServiceName": "Project-Service", |
|||
"LoadBalancerOptions": { |
|||
"Type": "LeastConnection" |
|||
}, |
|||
"UpstreamPathTemplate": "/ProjectName/swagger.json", |
|||
"UpstreamHttpMethod": [ |
|||
"Get", |
|||
"Post", |
|||
"Put", |
|||
"Delete" |
|||
] |
|||
}, |
|||
{ |
|||
"DownstreamPathTemplate": "/{url}", |
|||
"DownstreamScheme": "http", |
|||
"ServiceName": "Project-Service", |
|||
"LoadBalancerOptions": { |
|||
"Type": "LeastConnection" |
|||
}, |
|||
"UpstreamPathTemplate": "/gateway/{url}", |
|||
"UpstreamHttpMethod": [ |
|||
"Get", |
|||
"Post", |
|||
"Put", |
|||
"Delete" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
{ |
|||
"Logging": { |
|||
"LogLevel": { |
|||
"Default": "Information", |
|||
"Microsoft": "Warning", |
|||
"Microsoft.Hosting.Lifetime": "Information" |
|||
} |
|||
}, |
|||
"AllowedHosts": "*", |
|||
"App": { |
|||
"SelfUrl": "http://localhost:44314", |
|||
"CorsOrigins": "http://localhost:4200" |
|||
}, |
|||
"GlobalConfiguration": { |
|||
}, |
|||
"Routes": [ |
|||
{ |
|||
"DownstreamPathTemplate": "/swagger/ProjectName/swagger.json", |
|||
"DownstreamScheme": "http", |
|||
"DownstreamHostAndPorts": [ |
|||
{ |
|||
"Host": "localhost", |
|||
"Port": 44315 |
|||
} |
|||
], |
|||
"UpstreamPathTemplate": "/ProjectName/swagger.json", |
|||
"UpstreamHttpMethod": [ |
|||
"Get", |
|||
"Post", |
|||
"Put", |
|||
"Delete" |
|||
] |
|||
}, |
|||
{ |
|||
"DownstreamPathTemplate": "/{url}", |
|||
"DownstreamScheme": "http", |
|||
"DownstreamHostAndPorts": [ |
|||
{ |
|||
"Host": "localhost", |
|||
"Port": 44315 |
|||
} |
|||
], |
|||
"UpstreamPathTemplate": "/gateway/{url}", |
|||
"UpstreamHttpMethod": [ |
|||
"Get", |
|||
"Post", |
|||
"Put", |
|||
"Delete" |
|||
] |
|||
}, |
|||
{ |
|||
"DownstreamPathTemplate": "/{url}", |
|||
"DownstreamScheme": "ws", |
|||
"DownstreamHostAndPorts": [ |
|||
{ |
|||
"Host": "localhost", |
|||
"Port": 44315 |
|||
} |
|||
], |
|||
"UpstreamPathTemplate": "/ws/{url}", |
|||
"UpstreamHttpMethod": [ |
|||
"Get", |
|||
"Post", |
|||
"Put", |
|||
"Delete" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
{ |
|||
"Logging": { |
|||
"LogLevel": { |
|||
"Default": "Information", |
|||
"Microsoft": "Warning", |
|||
"Microsoft.Hosting.Lifetime": "Information" |
|||
} |
|||
}, |
|||
"AllowedHosts": "*", |
|||
"App": { |
|||
"SelfUrl": "http://localhost:44314", |
|||
"CorsOrigins": "http://localhost:4200" |
|||
}, |
|||
"GlobalConfiguration": { |
|||
}, |
|||
"Routes": [ |
|||
{ |
|||
"DownstreamPathTemplate": "/swagger/ProjectName/swagger.json", |
|||
"DownstreamScheme": "http", |
|||
"DownstreamHostAndPorts": [ |
|||
{ |
|||
"Host": "localhost", |
|||
"Port": 44315 |
|||
} |
|||
], |
|||
"UpstreamPathTemplate": "/ProjectName/swagger.json", |
|||
"UpstreamHttpMethod": [ |
|||
"Get", |
|||
"Post", |
|||
"Put", |
|||
"Delete" |
|||
] |
|||
}, |
|||
{ |
|||
"DownstreamPathTemplate": "/{url}", |
|||
"DownstreamScheme": "http", |
|||
"DownstreamHostAndPorts": [ |
|||
{ |
|||
"Host": "localhost", |
|||
"Port": 44315 |
|||
} |
|||
], |
|||
"UpstreamPathTemplate": "/{url}", |
|||
"UpstreamHttpMethod": [ |
|||
"Get", |
|||
"Post", |
|||
"Put", |
|||
"Delete" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using System; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Domain.Services; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
using Volo.Abp.ObjectMapping; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace CompanyName.ProjectName.DataDictionaryManagement |
|||
{ |
|||
public abstract class DataDictionaryDomainService : DomainService |
|||
{ |
|||
protected Type ObjectMapperContext { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 工作单元管理器
|
|||
/// </summary>
|
|||
protected IUnitOfWorkManager UnitOfWorkManager => |
|||
LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>(); |
|||
|
|||
/// <summary>
|
|||
/// 分布式事件总线
|
|||
/// </summary>
|
|||
protected IDistributedEventBus DistributedEventBus => |
|||
LazyServiceProvider.LazyGetRequiredService<IDistributedEventBus>(); |
|||
|
|||
/// <summary>
|
|||
/// 对象映射器
|
|||
/// </summary>
|
|||
protected IObjectMapper ObjectMapper => LazyServiceProvider.LazyGetService<IObjectMapper>( |
|||
provider => |
|||
ObjectMapperContext == null |
|||
? provider.GetRequiredService<IObjectMapper>() |
|||
: (IObjectMapper)provider.GetRequiredService( |
|||
typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext))); |
|||
} |
|||
} |
|||
@ -1,14 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
<Import Project="../../../../common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net5.0</TargetFramework> |
|||
<RootNamespace>CompanyName.ProjectName.DataDictionaryManagement</RootNamespace> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.MongoDB" Version="$(AbpPackageVersion)" /> |
|||
<ProjectReference Include="..\CompanyName.ProjectName.DataDictionaryManagement.Domain\CompanyName.ProjectName.DataDictionaryManagement.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -1,3 +0,0 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -1,30 +0,0 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -1,20 +0,0 @@ |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace CompanyName.ProjectName.DataDictionaryManagement.MongoDB |
|||
{ |
|||
[ConnectionStringName(DataDictionaryManagementDbProperties.ConnectionStringName)] |
|||
public class DataDictionaryManagementMongoDbContext : AbpMongoDbContext, IDataDictionaryManagementMongoDbContext |
|||
{ |
|||
/* Add mongo collections here. Example: |
|||
* public IMongoCollection<Question> Questions => Collection<Question>(); |
|||
*/ |
|||
|
|||
protected override void CreateModel(IMongoModelBuilder modelBuilder) |
|||
{ |
|||
base.CreateModel(modelBuilder); |
|||
|
|||
modelBuilder.ConfigureDataDictionaryManagement(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,22 +0,0 @@ |
|||
using System; |
|||
using Volo.Abp; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace CompanyName.ProjectName.DataDictionaryManagement.MongoDB |
|||
{ |
|||
public static class DataDictionaryManagementMongoDbContextExtensions |
|||
{ |
|||
public static void ConfigureDataDictionaryManagement( |
|||
this IMongoModelBuilder builder, |
|||
Action<AbpMongoModelBuilderConfigurationOptions> optionsAction = null) |
|||
{ |
|||
Check.NotNull(builder, nameof(builder)); |
|||
|
|||
var options = new DataDictionaryManagementMongoModelBuilderConfigurationOptions( |
|||
DataDictionaryManagementDbProperties.DbTablePrefix |
|||
); |
|||
|
|||
optionsAction?.Invoke(options); |
|||
} |
|||
} |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace CompanyName.ProjectName.DataDictionaryManagement.MongoDB |
|||
{ |
|||
[DependsOn( |
|||
typeof(DataDictionaryManagementDomainModule), |
|||
typeof(AbpMongoDbModule) |
|||
)] |
|||
public class DataDictionaryManagementMongoDbModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddMongoDbContext<DataDictionaryManagementMongoDbContext>(options => |
|||
{ |
|||
/* Add custom repositories here. Example: |
|||
* options.AddRepository<Question, MongoQuestionRepository>(); |
|||
*/ |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,14 +0,0 @@ |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace CompanyName.ProjectName.DataDictionaryManagement.MongoDB |
|||
{ |
|||
public class DataDictionaryManagementMongoModelBuilderConfigurationOptions : AbpMongoModelBuilderConfigurationOptions |
|||
{ |
|||
public DataDictionaryManagementMongoModelBuilderConfigurationOptions( |
|||
[NotNull] string collectionPrefix = "") |
|||
: base(collectionPrefix) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,13 +0,0 @@ |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace CompanyName.ProjectName.DataDictionaryManagement.MongoDB |
|||
{ |
|||
[ConnectionStringName(DataDictionaryManagementDbProperties.ConnectionStringName)] |
|||
public interface IDataDictionaryManagementMongoDbContext : IAbpMongoDbContext |
|||
{ |
|||
/* Define mongo collections here. Example: |
|||
* IMongoCollection<Question> Questions { get; } |
|||
*/ |
|||
} |
|||
} |
|||
@ -1,24 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
using CompanyName.ProjectName.NotificationManagement.Notifications.Dtos; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.Notifications |
|||
{ |
|||
public interface ICommandNotificationAppService : IApplicationService |
|||
{ |
|||
/// <summary>
|
|||
/// 消息设置为已读
|
|||
/// </summary>
|
|||
/// <param name="input"></param>
|
|||
/// <returns></returns>
|
|||
Task SetReadAsync(SetReadInput input); |
|||
|
|||
/// <summary>
|
|||
/// 创建一个消息
|
|||
/// 测试使用
|
|||
/// </summary>
|
|||
/// <param name="input"></param>
|
|||
/// <returns></returns>
|
|||
Task CreateAsync(CreateNotificationInput input); |
|||
} |
|||
} |
|||
@ -1,12 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.Samples |
|||
{ |
|||
public interface ISampleAppService : IApplicationService |
|||
{ |
|||
Task<SampleDto> GetAsync(); |
|||
|
|||
Task<SampleDto> GetAuthorizedAsync(); |
|||
} |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
namespace CompanyName.ProjectName.NotificationManagement.Samples |
|||
{ |
|||
public class SampleDto |
|||
{ |
|||
public int Value { get; set; } |
|||
} |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
using CompanyName.ProjectName.NotificationManagement.Notifications.Dtos; |
|||
using Volo.Abp.Users; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.Notifications |
|||
{ |
|||
public class CommandNotificationAppService : NotificationManagementAppService, ICommandNotificationAppService |
|||
{ |
|||
private readonly NotificationManager _notificationManager; |
|||
|
|||
private readonly ICurrentUser _currentUser; |
|||
public CommandNotificationAppService(NotificationManager notificationManager, ICurrentUser currentUser) |
|||
{ |
|||
_notificationManager = notificationManager; |
|||
_currentUser = currentUser; |
|||
} |
|||
|
|||
public Task SetReadAsync(SetReadInput input) |
|||
{ |
|||
return _notificationManager.SetReadAsync(input.Id, input.ReceiveId); |
|||
} |
|||
|
|||
public async Task CreateAsync(CreateNotificationInput input) |
|||
{ |
|||
if (_currentUser.Id != null) |
|||
await _notificationManager.CreateAsync(input.Title, input.Content, _currentUser.Id.Value, input.ReceiveIds, |
|||
input.MessageType); |
|||
} |
|||
} |
|||
} |
|||
4
aspnet-core/modules/NotificationManagement/src/CompanyName.ProjectName.NotificationManagement.Application/Notifications/DistributedEventHandlers/CreatedNotificationDistributedEventHandler.cs → aspnet-core/modules/NotificationManagement/src/CompanyName.ProjectName.NotificationManagement.Application/Notifications/DistributedEventHandlers/NotificationCreatedDistributedEventHandler.cs
4
aspnet-core/modules/NotificationManagement/src/CompanyName.ProjectName.NotificationManagement.Application/Notifications/DistributedEventHandlers/CreatedNotificationDistributedEventHandler.cs → aspnet-core/modules/NotificationManagement/src/CompanyName.ProjectName.NotificationManagement.Application/Notifications/DistributedEventHandlers/NotificationCreatedDistributedEventHandler.cs
@ -1,29 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.Samples |
|||
{ |
|||
public class SampleAppService : NotificationManagementAppService, ISampleAppService |
|||
{ |
|||
public Task<SampleDto> GetAsync() |
|||
{ |
|||
return Task.FromResult( |
|||
new SampleDto |
|||
{ |
|||
Value = 42 |
|||
} |
|||
); |
|||
} |
|||
|
|||
[Authorize] |
|||
public Task<SampleDto> GetAuthorizedAsync() |
|||
{ |
|||
return Task.FromResult( |
|||
new SampleDto |
|||
{ |
|||
Value = 42 |
|||
} |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -1,26 +1,30 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="../../../../common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net5.0</TargetFramework> |
|||
<RootNamespace>CompanyName.ProjectName.NotificationManagement</RootNamespace> |
|||
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Validation" Version="$(AbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="5.0.*" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<EmbeddedResource Include="Localization\NotificationManagement\*.json" /> |
|||
<Content Remove="Localization\NotificationManagement\*.json" /> |
|||
</ItemGroup> |
|||
|
|||
<Import Project="../../../../common.props"/> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net5.0</TargetFramework> |
|||
<RootNamespace>CompanyName.ProjectName.NotificationManagement</RootNamespace> |
|||
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Validation" Version="$(AbpPackageVersion)"/> |
|||
<PackageReference Include="Volo.Abp.AutoMapper" Version="$(AbpPackageVersion)"/> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="5.0.*"/> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<EmbeddedResource Include="Localization\NotificationManagement\*.json"/> |
|||
<Content Remove="Localization\NotificationManagement\*.json"/> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\frameworks\Extensions\src\Lion.Abp.Extension\Lion.Abp.Extension.csproj"/> |
|||
</ItemGroup> |
|||
|
|||
|
|||
</Project> |
|||
|
|||
@ -1,13 +1,36 @@ |
|||
using CompanyName.ProjectName.Extensions.Volo.Abp; |
|||
using System; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Domain.Services; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
using Volo.Abp.ObjectMapping; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement |
|||
{ |
|||
public abstract class NotificationManagementDomainService : BaseDomainService |
|||
public abstract class NotificationManagementDomainService : DomainService |
|||
{ |
|||
protected NotificationManagementDomainService() |
|||
{ |
|||
ObjectMapperContext = typeof(NotificationManagementDomainModule); |
|||
} |
|||
protected Type ObjectMapperContext { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 工作单元管理器
|
|||
/// </summary>
|
|||
protected IUnitOfWorkManager UnitOfWorkManager => |
|||
LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>(); |
|||
|
|||
/// <summary>
|
|||
/// 分布式事件总线
|
|||
/// </summary>
|
|||
protected IDistributedEventBus DistributedEventBus => |
|||
LazyServiceProvider.LazyGetRequiredService<IDistributedEventBus>(); |
|||
|
|||
/// <summary>
|
|||
/// 对象映射器
|
|||
/// </summary>
|
|||
protected IObjectMapper ObjectMapper => LazyServiceProvider.LazyGetService<IObjectMapper>( |
|||
provider => |
|||
ObjectMapperContext == null |
|||
? provider.GetRequiredService<IObjectMapper>() |
|||
: (IObjectMapper)provider.GetRequiredService( |
|||
typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext))); |
|||
} |
|||
} |
|||
@ -1,15 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="../../../../common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net5.0</TargetFramework> |
|||
<RootNamespace>CompanyName.ProjectName.NotificationManagement</RootNamespace> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.MongoDB" Version="$(AbpPackageVersion)" /> |
|||
<ProjectReference Include="..\CompanyName.ProjectName.NotificationManagement.Domain\CompanyName.ProjectName.NotificationManagement.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -1,3 +0,0 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -1,30 +0,0 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -1,13 +0,0 @@ |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.MongoDB |
|||
{ |
|||
[ConnectionStringName(NotificationManagementDbProperties.ConnectionStringName)] |
|||
public interface INotificationManagementMongoDbContext : IAbpMongoDbContext |
|||
{ |
|||
/* Define mongo collections here. Example: |
|||
* IMongoCollection<Question> Questions { get; } |
|||
*/ |
|||
} |
|||
} |
|||
@ -1,20 +0,0 @@ |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.MongoDB |
|||
{ |
|||
[ConnectionStringName(NotificationManagementDbProperties.ConnectionStringName)] |
|||
public class NotificationManagementMongoDbContext : AbpMongoDbContext, INotificationManagementMongoDbContext |
|||
{ |
|||
/* Add mongo collections here. Example: |
|||
* public IMongoCollection<Question> Questions => Collection<Question>(); |
|||
*/ |
|||
|
|||
protected override void CreateModel(IMongoModelBuilder modelBuilder) |
|||
{ |
|||
base.CreateModel(modelBuilder); |
|||
|
|||
modelBuilder.ConfigureNotificationManagement(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,22 +0,0 @@ |
|||
using System; |
|||
using Volo.Abp; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.MongoDB |
|||
{ |
|||
public static class NotificationManagementMongoDbContextExtensions |
|||
{ |
|||
public static void ConfigureNotificationManagement( |
|||
this IMongoModelBuilder builder, |
|||
Action<AbpMongoModelBuilderConfigurationOptions> optionsAction = null) |
|||
{ |
|||
Check.NotNull(builder, nameof(builder)); |
|||
|
|||
var options = new NotificationManagementMongoModelBuilderConfigurationOptions( |
|||
NotificationManagementDbProperties.DbTablePrefix |
|||
); |
|||
|
|||
optionsAction?.Invoke(options); |
|||
} |
|||
} |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.MongoDB |
|||
{ |
|||
[DependsOn( |
|||
typeof(NotificationManagementDomainModule), |
|||
typeof(AbpMongoDbModule) |
|||
)] |
|||
public class NotificationManagementMongoDbModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddMongoDbContext<NotificationManagementMongoDbContext>(options => |
|||
{ |
|||
/* Add custom repositories here. Example: |
|||
* options.AddRepository<Question, MongoQuestionRepository>(); |
|||
*/ |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,14 +0,0 @@ |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.MongoDB |
|||
{ |
|||
public class NotificationManagementMongoModelBuilderConfigurationOptions : AbpMongoModelBuilderConfigurationOptions |
|||
{ |
|||
public NotificationManagementMongoModelBuilderConfigurationOptions( |
|||
[NotNull] string collectionPrefix = "") |
|||
: base(collectionPrefix) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.Samples |
|||
{ |
|||
public class SampleAppService_Tests : NotificationManagementApplicationTestBase |
|||
{ |
|||
private readonly ISampleAppService _sampleAppService; |
|||
|
|||
public SampleAppService_Tests() |
|||
{ |
|||
_sampleAppService = GetRequiredService<ISampleAppService>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task GetAsync() |
|||
{ |
|||
var result = await _sampleAppService.GetAsync(); |
|||
result.Value.ShouldBe(42); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task GetAuthorizedAsync() |
|||
{ |
|||
var result = await _sampleAppService.GetAuthorizedAsync(); |
|||
result.Value.ShouldBe(42); |
|||
} |
|||
} |
|||
} |
|||
@ -1,17 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
using Xunit; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.Samples |
|||
{ |
|||
public class SampleManager_Tests : NotificationManagementDomainTestBase |
|||
{ |
|||
//private readonly SampleManager _sampleManager;
|
|||
|
|||
public SampleManager_Tests() |
|||
{ |
|||
//_sampleManager = GetRequiredService<SampleManager>();
|
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|||
@ -1,12 +0,0 @@ |
|||
using CompanyName.ProjectName.NotificationManagement.Samples; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.EntityFrameworkCore.Samples |
|||
{ |
|||
public class SampleRepository_Tests : SampleRepository_Tests<NotificationManagementEntityFrameworkCoreTestModule> |
|||
{ |
|||
/* Don't write custom repository tests here, instead write to |
|||
* the base class. |
|||
* One exception can be some specific tests related to EF core. |
|||
*/ |
|||
} |
|||
} |
|||
@ -1,22 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Modularity; |
|||
using Xunit; |
|||
|
|||
namespace CompanyName.ProjectName.NotificationManagement.Samples |
|||
{ |
|||
/* Write your custom repository tests like that, in this project, as abstract classes. |
|||
* Then inherit these abstract classes from EF Core & MongoDB test projects. |
|||
* In this way, both database providers are tests with the same set tests. |
|||
*/ |
|||
public abstract class SampleRepository_Tests<TStartupModule> : NotificationManagementTestBase<TStartupModule> |
|||
where TStartupModule : IAbpModule |
|||
{ |
|||
//private readonly ISampleRepository _sampleRepository;
|
|||
|
|||
protected SampleRepository_Tests() |
|||
{ |
|||
//_sampleRepository = GetRequiredService<ISampleRepository>();
|
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -1,17 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net5.0</TargetFramework> |
|||
<RootNamespace>CompanyName.ProjectName.QueryManagement</RootNamespace> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="$(AbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Authorization" Version="$(AbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Identity.Application.Contracts" Version="$(AbpPackageVersion)" /> |
|||
<ProjectReference Include="..\CompanyName.ProjectName.QueryManagement.Domain.Shared\CompanyName.ProjectName.QueryManagement.Domain.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -1,12 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
using CompanyName.ProjectName.Extensions.Customs.Dtos; |
|||
using CompanyName.ProjectName.QueryManagement.ElasticSearchs.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace CompanyName.ProjectName.QueryManagement.ElasticSearchs |
|||
{ |
|||
public interface ILogAppService : IApplicationService |
|||
{ |
|||
Task<CustomePagedResultDto<PagingElasticSearchLogOutput>> PaingLogAsync(PagingElasticSearchLogInput input); |
|||
} |
|||
} |
|||
@ -1,3 +0,0 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -1,30 +0,0 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -1,21 +0,0 @@ |
|||
using CompanyName.ProjectName.QueryManagement.Localization; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace CompanyName.ProjectName.QueryManagement.Permissions |
|||
{ |
|||
public class QueryManagementPermissionDefinitionProvider : PermissionDefinitionProvider |
|||
{ |
|||
public override void Define(IPermissionDefinitionContext context) |
|||
{ |
|||
var abpIdentityGroup = context.GetGroup(IdentityPermissions.GroupName); |
|||
var esManagement = abpIdentityGroup.AddPermission(QueryManagementPermissions.SystemManagement.ES, L("Permission:ESManagement")); |
|||
} |
|||
|
|||
private static LocalizableString L(string name) |
|||
{ |
|||
return LocalizableString.Create<QueryManagementResource>(name); |
|||
} |
|||
} |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
using Volo.Abp.Reflection; |
|||
|
|||
namespace CompanyName.ProjectName.QueryManagement.Permissions |
|||
{ |
|||
public class QueryManagementPermissions |
|||
{ |
|||
public const string GroupName = "QueryManagement"; |
|||
|
|||
public static string[] GetAll() |
|||
{ |
|||
return ReflectionHelper.GetPublicConstantsRecursively(typeof(QueryManagementPermissions)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 系统管理扩展权限
|
|||
/// </summary>
|
|||
public static class SystemManagement |
|||
{ |
|||
public const string Default = "System"; |
|||
public const string ES = Default + ".ES"; |
|||
} |
|||
} |
|||
} |
|||
@ -1,16 +0,0 @@ |
|||
using Volo.Abp.Application; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Authorization; |
|||
|
|||
namespace CompanyName.ProjectName.QueryManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(QueryManagementDomainSharedModule), |
|||
typeof(AbpDddApplicationContractsModule), |
|||
typeof(AbpAuthorizationModule) |
|||
)] |
|||
public class QueryManagementApplicationContractsModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -1,18 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net5.0</TargetFramework> |
|||
<RootNamespace>CompanyName.ProjectName.QueryManagement</RootNamespace> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.AutoMapper" Version="$(AbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Ddd.Application" Version="$(AbpPackageVersion)" /> |
|||
<ProjectReference Include="..\CompanyName.ProjectName.QueryManagement.Application.Contracts\CompanyName.ProjectName.QueryManagement.Application.Contracts.csproj" /> |
|||
<ProjectReference Include="..\CompanyName.ProjectName.QueryManagement.Domain\CompanyName.ProjectName.QueryManagement.Domain.csproj" /> |
|||
<ProjectReference Include="..\CompanyName.ProjectName.QueryManagement.ElasticSearch\CompanyName.ProjectName.QueryManagement.ElasticSearch.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -1,35 +0,0 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using CompanyName.ProjectName.Extensions.Customs.Dtos; |
|||
using CompanyName.ProjectName.QueryManagement.ElasticSearchs.Dtos; |
|||
using Microsoft.Extensions.Configuration; |
|||
|
|||
namespace CompanyName.ProjectName.QueryManagement.ElasticSearchs |
|||
{ |
|||
public class LogAppService : QueryManagementAppService, ILogAppService |
|||
{ |
|||
private readonly ICompanyNameProjectNameLogRepository _companyNameProjectNameLogRepository; |
|||
private readonly IConfiguration _configuration; |
|||
|
|||
public LogAppService( |
|||
ICompanyNameProjectNameLogRepository companyNameProjectNameLogRepository, |
|||
IConfiguration configuration) |
|||
{ |
|||
_companyNameProjectNameLogRepository = companyNameProjectNameLogRepository; |
|||
_configuration = configuration; |
|||
} |
|||
|
|||
public async Task<CustomePagedResultDto<PagingElasticSearchLogOutput>> PaingLogAsync(PagingElasticSearchLogInput input) |
|||
{ |
|||
var enabled = _configuration.GetValue<bool>("LogToElasticSearch:Enabled", false); |
|||
if (enabled) |
|||
{ |
|||
return await _companyNameProjectNameLogRepository.PaingAsync(input); |
|||
} |
|||
else |
|||
{ |
|||
return new CustomePagedResultDto<PagingElasticSearchLogOutput>(0, new List<PagingElasticSearchLogOutput>()); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue