From 8ead6c59c0fa4878ee2327a75f133d8fe0b42c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=B7=B3?= Date: Thu, 12 Jan 2023 18:30:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84ddd=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=8F=8A=E9=94=99=E8=AF=AF=E5=BC=82=E5=B8=B8=E4=B8=AD=E9=97=B4?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AutoIocAddExtensions.cs | 80 --- .../Yi.Framework.AspNetCore.csproj | 4 - .../YiFrameworkAspNetCoreModule.cs | 23 - .../Yi.Framework.BackgroundJobs/Class1.cs | 7 - .../Yi.Framework.BackgroundJobs.csproj | 9 - .../Attribute/AppServiceAttribute.cs | 2 +- .../DependencyInjection/IScopedDependency.cs | 12 + .../ISingletonDependency.cs | 12 + .../ITransientDependency.cs | 12 + .../Yi.Framework.Core/Enum/ResultCodeEnum.cs | 26 + .../Exceptions/BusinessException.cs | 52 ++ .../Exceptions/ExceptionExtensions.cs | 42 ++ .../Exceptions/IHasErrorCode.cs | 14 + .../Exceptions/IHasErrorDetails.cs | 13 + .../Exceptions/IHasLogLevel.cs | 14 + .../Exceptions/UserFriendlyException.cs | 39 ++ .../Extensions/AutoIocAddExtensions.cs | 112 ++++ .../Extensions/ErrorHandExtensions.cs | 57 ++ .../Yi.Framework.Core/Helper/Base32Helper.cs | 101 ++++ .../Yi.Framework.Core/Helper/ConsoleHelper.cs | 54 ++ .../Yi.Framework.Core/Helper/DateHelper.cs | 58 ++ .../Helper/DistinctHelper.cs | 42 ++ .../Yi.Framework.Core/Helper/FileHelper.cs | 490 +++++++++++++++++ .../Yi.Framework.Core/Helper/HtmlHelper.cs | 24 + .../Yi.Framework.Core/Helper/HttpHelper.cs | 122 +++++ .../Yi.Framework.Core/Helper/IdHelper.cs | 16 + .../Yi.Framework.Core/Helper/IpHelper.cs | 56 ++ .../Yi.Framework.Core/Helper/JsonHelper.cs | 509 ++++++++++++++++++ .../Yi.Framework.Core/Helper/MD5Hepler.cs | 132 +++++ .../Yi.Framework.Core/Helper/MimeHelper.cs | 244 +++++++++ .../Yi.Framework.Core/Helper/RSAFileHelper.cs | 34 ++ .../Yi.Framework.Core/Helper/RSAHelper.cs | 390 ++++++++++++++ .../Yi.Framework.Core/Helper/RandomHelper.cs | 99 ++++ .../Helper/SnowflakeHelper.cs | 99 ++++ .../Yi.Framework.Core/Helper/StringHelper.cs | 111 ++++ .../Yi.Framework.Core/Helper/TreeHelper.cs | 68 +++ .../Yi.Framework.Core/Helper/UnicodeHelper.cs | 47 ++ .../Yi.Framework.Core/Helper/UrlHelper.cs | 23 + .../Yi.Framework.Core/Helper/XmlHelper.cs | 51 ++ .../YiFrameworkCoreModule.cs | 7 +- .../Dtos/EntityDto.cs | 31 ++ .../Dtos/IEntityDto.cs | 17 + .../Entities/Entity.cs | 50 ++ .../Entities/IEntity.cs | 23 + .../Services/ApplicationService.cs | 12 + .../Services/IApplicationService.cs | 12 + .../Yi.Framework.Ddd.csproj | 1 - .../Yi.Framework.Web/TestEntity.cs | 7 +- .../Yi.Framework.Web/Yi.Framework.Web.csproj | 1 + src/Yi.Framework/Yi.Framework.sln | 9 +- 50 files changed, 3334 insertions(+), 136 deletions(-) delete mode 100644 src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/AutoIocAddExtensions.cs delete mode 100644 src/Yi.Framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs delete mode 100644 src/Yi.Framework/Yi.Framework.BackgroundJobs/Class1.cs delete mode 100644 src/Yi.Framework/Yi.Framework.BackgroundJobs/Yi.Framework.BackgroundJobs.csproj create mode 100644 src/Yi.Framework/Yi.Framework.Core/DependencyInjection/IScopedDependency.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/DependencyInjection/ISingletonDependency.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/DependencyInjection/ITransientDependency.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Enum/ResultCodeEnum.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Exceptions/BusinessException.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Exceptions/ExceptionExtensions.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasErrorCode.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasErrorDetails.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasLogLevel.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Exceptions/UserFriendlyException.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Extensions/AutoIocAddExtensions.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Extensions/ErrorHandExtensions.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/Base32Helper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/ConsoleHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/DateHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/DistinctHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/FileHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/HtmlHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/HttpHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/IdHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/IpHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/JsonHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/MD5Hepler.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/MimeHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/RSAFileHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/RSAHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/RandomHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/SnowflakeHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/StringHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/TreeHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/UnicodeHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/UrlHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Core/Helper/XmlHelper.cs create mode 100644 src/Yi.Framework/Yi.Framework.Ddd.Application/Dtos/EntityDto.cs create mode 100644 src/Yi.Framework/Yi.Framework.Ddd.Application/Dtos/IEntityDto.cs create mode 100644 src/Yi.Framework/Yi.Framework.Ddd.Application/Entities/Entity.cs create mode 100644 src/Yi.Framework/Yi.Framework.Ddd.Application/Entities/IEntity.cs create mode 100644 src/Yi.Framework/Yi.Framework.Ddd.Application/Services/ApplicationService.cs create mode 100644 src/Yi.Framework/Yi.Framework.Ddd.Application/Services/IApplicationService.cs diff --git a/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/AutoIocAddExtensions.cs b/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/AutoIocAddExtensions.cs deleted file mode 100644 index db06ece0..00000000 --- a/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/AutoIocAddExtensions.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Yi.Framework.Core.Attribute; - -namespace Microsoft.Extensions.DependencyInjection -{ - public static class AutoIocAddExtensions - { - public static IServiceCollection AddAutoIocServer(this IServiceCollection services, params string[] assemblyStr) - { - foreach (var a in assemblyStr) - { - RegIoc(services, Assembly.Load(a)); - } - return services; - } - - /// - /// 扫描全部 - /// - /// - /// - public static IServiceCollection AddAutoIocServer(this IServiceCollection services) - { - var assemblys= AppDomain.CurrentDomain.GetAssemblies(); - foreach (var a in assemblys) - { - RegIoc(services, a); - } - return services; - } - private static void RegIoc(IServiceCollection services, Assembly assembly) - { - foreach (var type in assembly.GetTypes()) - { - - var serviceAttribute = type.GetCustomAttribute(); - if (serviceAttribute is not null) - { - //泛型类需要单独进行处理 - //情况1:使用自定义[AppService(ServiceType = typeof(注册抽象或者接口))],手动去注册,放type即可 - var serviceType = serviceAttribute.ServiceType; - //情况2 自动去找接口,如果存在就是接口,如果不存在就是本身 - if (serviceType == null) - { - //获取最靠近的接口 - var firstInter = type .GetInterfaces().LastOrDefault(); - if (firstInter is null) - { - serviceType = type; - } - else - { - serviceType = firstInter; - } - } - - switch (serviceAttribute.ServiceLifetime) - { - case LifeTime.Singleton: - services.AddSingleton(serviceType, type); - break; - case LifeTime.Scoped: - services.AddScoped(serviceType, type); - break; - case LifeTime.Transient: - services.AddTransient(serviceType, type); - break; - } - - } - } - } - } -} diff --git a/src/Yi.Framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj b/src/Yi.Framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj index d711e643..00516e6b 100644 --- a/src/Yi.Framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj +++ b/src/Yi.Framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj @@ -12,10 +12,6 @@ - - - - diff --git a/src/Yi.Framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs b/src/Yi.Framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs deleted file mode 100644 index e541aec0..00000000 --- a/src/Yi.Framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using StartupModules; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Yi.Framework.AspNetCore -{ - internal class YiFrameworkAspNetCoreModule : IStartupModule - { - public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context) - { - } - - public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) - { - services.AddAutoIocServer(); - } - } -} diff --git a/src/Yi.Framework/Yi.Framework.BackgroundJobs/Class1.cs b/src/Yi.Framework/Yi.Framework.BackgroundJobs/Class1.cs deleted file mode 100644 index b1f532b6..00000000 --- a/src/Yi.Framework/Yi.Framework.BackgroundJobs/Class1.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Yi.Framework.BackgroundJobs -{ - public class Class1 - { - - } -} \ No newline at end of file diff --git a/src/Yi.Framework/Yi.Framework.BackgroundJobs/Yi.Framework.BackgroundJobs.csproj b/src/Yi.Framework/Yi.Framework.BackgroundJobs/Yi.Framework.BackgroundJobs.csproj deleted file mode 100644 index 132c02c5..00000000 --- a/src/Yi.Framework/Yi.Framework.BackgroundJobs/Yi.Framework.BackgroundJobs.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - net6.0 - enable - enable - - - diff --git a/src/Yi.Framework/Yi.Framework.Core/Attribute/AppServiceAttribute.cs b/src/Yi.Framework/Yi.Framework.Core/Attribute/AppServiceAttribute.cs index af68ec48..e9e1ddc7 100644 --- a/src/Yi.Framework/Yi.Framework.Core/Attribute/AppServiceAttribute.cs +++ b/src/Yi.Framework/Yi.Framework.Core/Attribute/AppServiceAttribute.cs @@ -16,7 +16,7 @@ namespace Yi.Framework.Core.Attribute /// 服务声明周期 /// 不给默认值的话注册的是作用域 /// - public LifeTime ServiceLifetime { get; set; } = LifeTime.Scoped; + public LifeTime ServiceLifetime { get; set; } = LifeTime.Transient; /// /// 指定服务类型 /// diff --git a/src/Yi.Framework/Yi.Framework.Core/DependencyInjection/IScopedDependency.cs b/src/Yi.Framework/Yi.Framework.Core/DependencyInjection/IScopedDependency.cs new file mode 100644 index 00000000..2b5f628c --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/DependencyInjection/IScopedDependency.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.DependencyInjection +{ + internal interface IScopedDependency + { + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/DependencyInjection/ISingletonDependency.cs b/src/Yi.Framework/Yi.Framework.Core/DependencyInjection/ISingletonDependency.cs new file mode 100644 index 00000000..d79d686d --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/DependencyInjection/ISingletonDependency.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.DependencyInjection +{ + public interface ISingletonDependency + { + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/DependencyInjection/ITransientDependency.cs b/src/Yi.Framework/Yi.Framework.Core/DependencyInjection/ITransientDependency.cs new file mode 100644 index 00000000..b075939d --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/DependencyInjection/ITransientDependency.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.DependencyInjection +{ + public interface ITransientDependency + { + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Enum/ResultCodeEnum.cs b/src/Yi.Framework/Yi.Framework.Core/Enum/ResultCodeEnum.cs new file mode 100644 index 00000000..ebe11f1d --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Enum/ResultCodeEnum.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Enum +{ + public enum ResultCodeEnum + { + /// + /// 操作成功。 + /// + Success = 200, + + /// + /// 操作不成功 + /// + NotSuccess = 500, + + /// + /// 无权限 + /// + NoPermission = 401 + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Exceptions/BusinessException.cs b/src/Yi.Framework/Yi.Framework.Core/Exceptions/BusinessException.cs new file mode 100644 index 00000000..382226d4 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Exceptions/BusinessException.cs @@ -0,0 +1,52 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.Enum; + +namespace Yi.Framework.Core.Exceptions +{ + public class BusinessException : Exception, + IHasErrorCode, + IHasErrorDetails, + IHasLogLevel + { + public ResultCodeEnum Code { get; set; } + + public string? Details { get; set; } + + public LogLevel LogLevel { get; set; } + + public BusinessException( + ResultCodeEnum code = ResultCodeEnum.NotSuccess, + string? message = null, + string? details = null, + Exception? innerException = null, + LogLevel logLevel = LogLevel.Warning) + : base(message, innerException) + { + Code = code; + Details = details; + LogLevel = logLevel; + } + + /// + /// 序列化参数的构造函数 + /// + public BusinessException(SerializationInfo serializationInfo, StreamingContext context) + : base(serializationInfo, context) + { + + } + + public BusinessException WithData(string name, object value) + { + Data[name] = value; + return this; + } + + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Exceptions/ExceptionExtensions.cs b/src/Yi.Framework/Yi.Framework.Core/Exceptions/ExceptionExtensions.cs new file mode 100644 index 00000000..e7157b59 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Exceptions/ExceptionExtensions.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.ExceptionServices; +using Microsoft.Extensions.Logging; +using Yi.Framework.Core.Enum; + +namespace Yi.Framework.Core.Exceptions; + +/// +/// չ +/// +public static class ExceptionExtensions +{ + /// + /// ʹ ٴ׳쳣 + /// + /// Exception to be re-thrown + public static void ReThrow(this Exception exception) + { + ExceptionDispatchInfo.Capture(exception).Throw(); + } + + /// + /// ȡ쳣е־ȼ + /// + /// + /// + /// + public static LogLevel GetLogLevel(this Exception exception, LogLevel defaultLevel = LogLevel.Error) + { + return (exception as IHasLogLevel)?.LogLevel ?? defaultLevel; + } + /// + /// ȡ쳣е־ + /// + /// + /// + /// + public static ResultCodeEnum GetLogErrorCode(this Exception exception, ResultCodeEnum defaultCode = ResultCodeEnum.NotSuccess) + { + return (exception as IHasErrorCode)?.Code ?? defaultCode; + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasErrorCode.cs b/src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasErrorCode.cs new file mode 100644 index 00000000..f7586014 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasErrorCode.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.Enum; + +namespace Yi.Framework.Core.Exceptions +{ + internal interface IHasErrorCode + { + ResultCodeEnum Code { get; } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasErrorDetails.cs b/src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasErrorDetails.cs new file mode 100644 index 00000000..2ea6e71f --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasErrorDetails.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Exceptions +{ + public interface IHasErrorDetails + { + string? Details { get; } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasLogLevel.cs b/src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasLogLevel.cs new file mode 100644 index 00000000..038eaa32 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Exceptions/IHasLogLevel.cs @@ -0,0 +1,14 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Exceptions +{ + public interface IHasLogLevel + { + LogLevel LogLevel { get; set; } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Exceptions/UserFriendlyException.cs b/src/Yi.Framework/Yi.Framework.Core/Exceptions/UserFriendlyException.cs new file mode 100644 index 00000000..0ede95d1 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Exceptions/UserFriendlyException.cs @@ -0,0 +1,39 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.Enum; + +namespace Yi.Framework.Core.Exceptions +{ + public class UserFriendlyException: BusinessException + { + public UserFriendlyException( + string message, + ResultCodeEnum code = ResultCodeEnum.NotSuccess, + string? details = null, + Exception? innerException = null, + LogLevel logLevel = LogLevel.Warning) + : base( + code, + message, + details, + innerException, + logLevel) + { + Details = details; + } + + /// + /// 序列化参数的构造函数 + /// + public UserFriendlyException(SerializationInfo serializationInfo, StreamingContext context) + : base(serializationInfo, context) + { + + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Extensions/AutoIocAddExtensions.cs b/src/Yi.Framework/Yi.Framework.Core/Extensions/AutoIocAddExtensions.cs new file mode 100644 index 00000000..51c7a895 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Extensions/AutoIocAddExtensions.cs @@ -0,0 +1,112 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.Attribute; +using Yi.Framework.Core.DependencyInjection; + +namespace Yi.Framework.Core.Extensions +{ + public static class AutoIocAddExtensions + { + public static IServiceCollection AddAutoIocServer(this IServiceCollection services, params string[] assemblyStr) + { + foreach (var a in assemblyStr) + { + RegIoc(services, Assembly.Load(a)); + } + return services; + } + + /// + /// 扫描全部 + /// + /// + /// + public static IServiceCollection AddAutoIocServer(this IServiceCollection services) + { + var assemblys = AppDomain.CurrentDomain.GetAssemblies(); + foreach (var a in assemblys) + { + RegIoc(services, a); + } + return services; + } + private static void RegIoc(IServiceCollection services, Assembly assembly) + { + foreach (var type in assembly.GetTypes()) + { + RegIocByAttribute(services, type); + RegIocByInterface(services, type); + } + } + + private static void RegIocByAttribute(IServiceCollection services, Type type) + { + var serviceAttribute = type.GetCustomAttribute(); + if (serviceAttribute is not null) + { + //泛型类需要单独进行处理 + //情况1:使用自定义[AppService(ServiceType = typeof(注册抽象或者接口))],手动去注册,放type即可 + var serviceType = serviceAttribute.ServiceType; + //情况2 自动去找接口,如果存在就是接口,如果不存在就是本身 + if (serviceType == null) + { + //获取最靠近的接口 + var firstInter = type.GetInterfaces().LastOrDefault(); + if (firstInter is null) + { + serviceType = type; + } + else + { + serviceType = firstInter; + } + } + + switch (serviceAttribute.ServiceLifetime) + { + case LifeTime.Singleton: + services.AddSingleton(serviceType, type); + break; + case LifeTime.Scoped: + services.AddScoped(serviceType, type); + break; + case LifeTime.Transient: + services.AddTransient(serviceType, type); + break; + } + + } + } + + private static void RegIocByInterface(IServiceCollection services, Type type) + { + var serviceInterfaces = type.GetInterfaces(); + if (serviceInterfaces is not null) + { + var serviceType = type; + var firstInter = type.GetInterfaces().LastOrDefault(); + if (firstInter is not null) + { + serviceType = firstInter; + } + if (serviceInterfaces.Contains(typeof(ITransientDependency))) + { + services.AddTransient(serviceType,type); + } + if (serviceInterfaces.Contains(typeof(IScopedDependency))) + { + services.AddScoped(serviceType,type); + } + if (serviceInterfaces.Contains(typeof(ISingletonDependency))) + { + services.AddSingleton(serviceType,type); + } + } + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Extensions/ErrorHandExtensions.cs b/src/Yi.Framework/Yi.Framework.Core/Extensions/ErrorHandExtensions.cs new file mode 100644 index 00000000..5c9e1129 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Extensions/ErrorHandExtensions.cs @@ -0,0 +1,57 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.Exceptions; + +namespace Yi.Framework.Core.Extensions +{ + public class ErrorHandMiddleware + { + private readonly RequestDelegate _next; + private readonly ILogger _logger; + //private readonly IErrorHandle _errorHandle; + public ErrorHandMiddleware(RequestDelegate next, ILoggerFactory loggerFactory /*, IErrorHandle errorHandle*/) + { + this._next = next; + this._logger = loggerFactory.CreateLogger(); + } + public async Task Invoke(HttpContext context) + { + bool isNext = true; + try + { + await _next(context); + } + catch (BusinessException businessEx) + { + var statusCode = 200; + //业务错误,不记录 + await context.Response.WriteAsync($"你好世界:友好错误,已经被中间件拦截"); + } + catch (Exception ex) + { + isNext = false; + _logger.LogError(ex, $"系统错误:{ex.Message}"); + //await _errorHandle.Invoer(context, ex); + var statusCode = context.Response.StatusCode; + context.Response.StatusCode = 500; + //系统错误,需要记录 + await context.Response.WriteAsync($"你好世界:系统错误,已经被中间件拦截"); + } + } + + } + + public static class ErrorHandExtensions + { + public static IApplicationBuilder UseErrorHandlingServer(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/Base32Helper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/Base32Helper.cs new file mode 100644 index 00000000..2f89bc1c --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/Base32Helper.cs @@ -0,0 +1,101 @@ +using System; +using System.Text; + +namespace Yi.Framework.Core.Helper +{ + public sealed class Base32Helper + { + + // the valid chars for the encoding + private static string ValidChars = "QAZ2WSX3" + "EDC4RFV5" + "TGB6YHN7" + "UJM8K9LP"; + + /// + /// Converts an array of bytes to a Base32-k string. + /// + public static string ToString(byte[] bytes) + { + StringBuilder sb = new StringBuilder(); // holds the base32 chars + byte index; + int hi = 5; + int currentByte = 0; + + while (currentByte < bytes.Length) + { + // do we need to use the next byte? + if (hi > 8) + { + // get the last piece from the current byte, shift it to the right + // and increment the byte counter + index = (byte)(bytes[currentByte++] >> (hi - 5)); + if (currentByte != bytes.Length) + { + // if we are not at the end, get the first piece from + // the next byte, clear it and shift it to the left + index = (byte)(((byte)(bytes[currentByte] << (16 - hi)) >> 3) | index); + } + + hi -= 3; + } + else if (hi == 8) + { + index = (byte)(bytes[currentByte++] >> 3); + hi -= 3; + } + else + { + + // simply get the stuff from the current byte + index = (byte)((byte)(bytes[currentByte] << (8 - hi)) >> 3); + hi += 5; + } + + sb.Append(ValidChars[index]); + } + + return sb.ToString(); + } + + + /// + /// Converts a Base32-k string into an array of bytes. + /// + /// + /// Input string s contains invalid Base32-k characters. + /// + public static byte[] FromBase32String(string str) + { + int numBytes = str.Length * 5 / 8; + byte[] bytes = new Byte[numBytes]; + + // all UPPERCASE chars + str = str.ToUpper(); + + int bit_buffer; + int currentCharIndex; + int bits_in_buffer; + + if (str.Length < 3) + { + bytes[0] = (byte)(ValidChars.IndexOf(str[0]) | ValidChars.IndexOf(str[1]) << 5); + return bytes; + } + + bit_buffer = (ValidChars.IndexOf(str[0]) | ValidChars.IndexOf(str[1]) << 5); + bits_in_buffer = 10; + currentCharIndex = 2; + for (int i = 0; i < bytes.Length; i++) + { + bytes[i] = (byte)bit_buffer; + bit_buffer >>= 8; + bits_in_buffer -= 8; + while (bits_in_buffer < 8 && currentCharIndex < str.Length) + { + bit_buffer |= ValidChars.IndexOf(str[currentCharIndex++]) << bits_in_buffer; + bits_in_buffer += 5; + } + } + + return bytes; + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/ConsoleHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/ConsoleHelper.cs new file mode 100644 index 00000000..dfd6a8ab --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/ConsoleHelper.cs @@ -0,0 +1,54 @@ +using System; + +namespace Yi.Framework.Core.Helper +{ + public static class ConsoleHelper + { + public static void WriteColorLine(string str, ConsoleColor color) + { + ConsoleColor currentForeColor = Console.ForegroundColor; + Console.ForegroundColor = color; + Console.WriteLine(str); + Console.ForegroundColor = currentForeColor; + } + + /// + /// 打印错误信息 + /// + /// 待打印的字符串 + /// 想要打印的颜色 + public static void WriteErrorLine(this string str, ConsoleColor color = ConsoleColor.Red) + { + WriteColorLine(str, color); + } + + /// + /// 打印警告信息 + /// + /// 待打印的字符串 + /// 想要打印的颜色 + public static void WriteWarningLine(this string str, ConsoleColor color = ConsoleColor.Yellow) + { + WriteColorLine(str, color); + } + /// + /// 打印正常信息 + /// + /// 待打印的字符串 + /// 想要打印的颜色 + public static void WriteInfoLine(this string str, ConsoleColor color = ConsoleColor.White) + { + WriteColorLine(str, color); + } + /// + /// 打印成功的信息 + /// + /// 待打印的字符串 + /// 想要打印的颜色 + public static void WriteSuccessLine(this string str, ConsoleColor color = ConsoleColor.Green) + { + WriteColorLine(str, color); + } + + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/DateHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/DateHelper.cs new file mode 100644 index 00000000..0ac37315 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/DateHelper.cs @@ -0,0 +1,58 @@ +using System; + +namespace Yi.Framework.Core.Helper +{ + public class DateHelper + { + public static DateTime StampToDateTime(string time) + { + time = time.Substring(0, 10); + double timestamp = Convert.ToInt64(time); + System.DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0); + dateTime = dateTime.AddSeconds(timestamp).ToLocalTime(); + return dateTime; + } + + public static string TimeSubTract(DateTime time1,DateTime time2) + { + TimeSpan subTract = time1.Subtract(time2); + return $"{subTract.Days} 天 {subTract.Hours} 时 {subTract.Minutes} 分 "; + } + /// + /// 时间戳转本地时间-时间戳精确到秒 + /// + public static DateTime ToLocalTimeDateBySeconds(long unix) + { + var dto = DateTimeOffset.FromUnixTimeSeconds(unix); + return dto.ToLocalTime().DateTime; + } + + /// + /// 时间转时间戳Unix-时间戳精确到秒 + /// + public static long ToUnixTimestampBySeconds(DateTime dt) + { + DateTimeOffset dto = new DateTimeOffset(dt); + return dto.ToUnixTimeSeconds(); + } + + + /// + /// 时间戳转本地时间-时间戳精确到毫秒 + /// + public static DateTime ToLocalTimeDateByMilliseconds(long unix) + { + var dto = DateTimeOffset.FromUnixTimeMilliseconds(unix); + return dto.ToLocalTime().DateTime; + } + + /// + /// 时间转时间戳Unix-时间戳精确到毫秒 + /// + public static long ToUnixTimestampByMilliseconds(DateTime dt) + { + DateTimeOffset dto = new DateTimeOffset(dt); + return dto.ToUnixTimeMilliseconds(); + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/DistinctHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/DistinctHelper.cs new file mode 100644 index 00000000..18df6efb --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/DistinctHelper.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Helper +{ + public class Compare : IEqualityComparer + { + private Func _getField; + public Compare(Func getfield) + { + this._getField = getfield; + } + public bool Equals(T? x, T? y) + { + return EqualityComparer.Default.Equals(_getField(x!), _getField(y!)); + } + + public int GetHashCode(T obj) + { + return EqualityComparer.Default.GetHashCode(this._getField(obj)!); + } + } + public static class DistinctHelper + { + /// + /// 自定义Distinct扩展方法 + /// + /// 要去重的对象类 + /// 自定义去重的字段类型 + /// 要去重的对象 + /// 获取自定义去重字段的委托 + /// + public static IEnumerable DistinctNew(this IEnumerable source, Func getfield) + { + return source.Distinct(new Compare(getfield)); + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/FileHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/FileHelper.cs new file mode 100644 index 00000000..7ae1c0c4 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/FileHelper.cs @@ -0,0 +1,490 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Yi.Framework.Common.Helper +{ + public class FileHelper : IDisposable + { + + private bool _alreadyDispose = false; + + + + #region 构造函数 + public FileHelper() + { + // + // TODO: 在此处添加构造函数逻辑 + // + } + ~FileHelper() + { + Dispose(); ; + } + + protected virtual void Dispose(bool isDisposing) + { + if (_alreadyDispose) return; + _alreadyDispose = true; + } + #endregion + + #region IDisposable 成员 + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + + #region 取得文件后缀名 + /**************************************** + * 函数名称:GetPostfixStr + * 功能说明:取得文件后缀名 + * 参 数:filename:文件名称 + * 调用示列: + * string filename = "aaa.aspx"; + * string s = EC.FileObj.GetPostfixStr(filename); + *****************************************/ + /// + /// 取后缀名 + /// + /// 文件名 + /// .gif|.html格式 + public static string GetPostfixStr(string filename) + { + int start = filename.LastIndexOf("."); + int length = filename.Length; + string postfix = filename.Substring(start, length - start); + return postfix; + } + #endregion + + #region 根据文件大小获取指定前缀的可用文件名 + /// + /// 根据文件大小获取指定前缀的可用文件名 + /// + /// 文件夹 + /// 文件前缀 + /// 文件大小(1m) + /// 文件后缀(.log) + /// 可用文件名 + //public static string GetAvailableFileWithPrefixOrderSize(string folderPath, string prefix, int size = 1 * 1024 * 1024, string ext = ".log") + //{ + // var allFiles = new DirectoryInfo(folderPath); + // var selectFiles = allFiles.GetFiles().Where(fi => fi.Name.ToLower().Contains(prefix.ToLower()) && fi.Extension.ToLower() == ext.ToLower() && fi.Length < size).OrderByDescending(d=>d.Name).ToList(); + + // if (selectFiles.Count > 0) + // { + // return selectFiles.FirstOrDefault().FullName; + // } + + // return Path.Combine(folderPath, $@"{prefix}_{DateTime.Now.DateToTimeStamp()}.log"); + //} + //public static string GetAvailableFileNameWithPrefixOrderSize(string _contentRoot, string prefix, int size = 1 * 1024 * 1024, string ext = ".log") + //{ + // var folderPath = Path.Combine(_contentRoot, "Log"); + // if (!Directory.Exists(folderPath)) + // { + // Directory.CreateDirectory(folderPath); + // } + + // var allFiles = new DirectoryInfo(folderPath); + // var selectFiles = allFiles.GetFiles().Where(fi => fi.Name.ToLower().Contains(prefix.ToLower()) && fi.Extension.ToLower() == ext.ToLower() && fi.Length < size).OrderByDescending(d => d.Name).ToList(); + + // if (selectFiles.Count > 0) + // { + // return selectFiles.FirstOrDefault().Name.Replace(".log",""); + // } + + // return $@"{prefix}_{DateTime.Now.DateToTimeStamp()}"; + //} + #endregion + + #region 写文件 + /**************************************** + * 函数名称:WriteFile + * 功能说明:写文件,会覆盖掉以前的内容 + * 参 数:Path:文件路径,Strings:文本内容 + * 调用示列: + * string Path = Server.MapPath("Default2.aspx"); + * string Strings = "这是我写的内容啊"; + * EC.FileObj.WriteFile(Path,Strings); + *****************************************/ + /// + /// 写文件 + /// + /// 文件路径 + /// 文件内容 + public static void WriteFile(string Path, string Strings) + { + if (!File.Exists(Path)) + { + FileStream f = File.Create(Path); + f.Close(); + } + StreamWriter f2 = new StreamWriter(Path, false, System.Text.Encoding.GetEncoding("gb2312")); + f2.Write(Strings); + f2.Close(); + f2.Dispose(); + } + + /// + /// 写文件 + /// + /// 文件路径 + /// 文件内容 + /// 编码格式 + public static void WriteFile(string Path, string Strings, Encoding encode) + { + if (!File.Exists(Path)) + { + FileStream f = File.Create(Path); + f.Close(); + } + StreamWriter f2 = new StreamWriter(Path, false, encode); + f2.Write(Strings); + f2.Close(); + f2.Dispose(); + } + #endregion + + #region 读文件 + /**************************************** + * 函数名称:ReadFile + * 功能说明:读取文本内容 + * 参 数:Path:文件路径 + * 调用示列: + * string Path = Server.MapPath("Default2.aspx"); + * string s = EC.FileObj.ReadFile(Path); + *****************************************/ + /// + /// 读文件 + /// + /// 文件路径 + /// + public static string ReadFile(string Path) + { + string s = ""; + if (!File.Exists(Path)) + s = "不存在相应的目录"; + else + { + StreamReader f2 = new StreamReader(Path, System.Text.Encoding.GetEncoding("gb2312")); + s = f2.ReadToEnd(); + f2.Close(); + f2.Dispose(); + } + + return s; + } + + /// + /// 读文件 + /// + /// 文件路径 + /// 编码格式 + /// + public static string ReadFile(string Path, Encoding encode) + { + string s = ""; + if (!File.Exists(Path)) + s = "不存在相应的目录"; + else + { + StreamReader f2 = new StreamReader(Path, encode); + s = f2.ReadToEnd(); + f2.Close(); + f2.Dispose(); + } + + return s; + } + #endregion + + #region 追加文件 + /**************************************** + * 函数名称:FileAdd + * 功能说明:追加文件内容 + * 参 数:Path:文件路径,strings:内容 + * 调用示列: + * string Path = Server.MapPath("Default2.aspx"); + * string Strings = "新追加内容"; + * EC.FileObj.FileAdd(Path, Strings); + *****************************************/ + /// + /// 追加文件 + /// + /// 文件路径 + /// 内容 + public static void FileAdd(string Path, string strings) + { + StreamWriter sw = File.AppendText(Path); + sw.Write(strings); + sw.Flush(); + sw.Close(); + } + #endregion + + #region 拷贝文件 + /**************************************** + * 函数名称:FileCoppy + * 功能说明:拷贝文件 + * 参 数:OrignFile:原始文件,NewFile:新文件路径 + * 调用示列: + * string orignFile = Server.MapPath("Default2.aspx"); + * string NewFile = Server.MapPath("Default3.aspx"); + * EC.FileObj.FileCoppy(OrignFile, NewFile); + *****************************************/ + /// + /// 拷贝文件 + /// + /// 原始文件 + /// 新文件路径 + public static void FileCoppy(string orignFile, string NewFile) + { + File.Copy(orignFile, NewFile, true); + } + + #endregion + + #region 删除文件 + /**************************************** + * 函数名称:FileDel + * 功能说明:删除文件 + * 参 数:Path:文件路径 + * 调用示列: + * string Path = Server.MapPath("Default3.aspx"); + * EC.FileObj.FileDel(Path); + *****************************************/ + /// + /// 删除文件 + /// + /// 路径 + public static void FileDel(string Path) + { + File.Delete(Path); + } + #endregion + + #region 移动文件 + /**************************************** + * 函数名称:FileMove + * 功能说明:移动文件 + * 参 数:OrignFile:原始路径,NewFile:新文件路径 + * 调用示列: + * string orignFile = Server.MapPath("../说明.txt"); + * string NewFile = Server.MapPath("http://www.cnblogs.com/说明.txt"); + * EC.FileObj.FileMove(OrignFile, NewFile); + *****************************************/ + /// + /// 移动文件 + /// + /// 原始路径 + /// 新路径 + public static void FileMove(string orignFile, string NewFile) + { + File.Move(orignFile, NewFile); + } + #endregion + + #region 在当前目录下创建目录 + /**************************************** + * 函数名称:FolderCreate + * 功能说明:在当前目录下创建目录 + * 参 数:OrignFolder:当前目录,NewFloder:新目录 + * 调用示列: + * string orignFolder = Server.MapPath("test/"); + * string NewFloder = "new"; + * EC.FileObj.FolderCreate(OrignFolder, NewFloder); + *****************************************/ + /// + /// 在当前目录下创建目录 + /// + /// 当前目录 + /// 新目录 + public static void FolderCreate(string orignFolder, string NewFloder) + { + Directory.SetCurrentDirectory(orignFolder); + Directory.CreateDirectory(NewFloder); + } + #endregion + + #region 递归删除文件夹目录及文件 + /**************************************** + * 函数名称:DeleteFolder + * 功能说明:递归删除文件夹目录及文件 + * 参 数:dir:文件夹路径 + * 调用示列: + * string dir = Server.MapPath("test/"); + * EC.FileObj.DeleteFolder(dir); + *****************************************/ + /// + /// 递归删除文件夹目录及文件 + /// + /// + /// + public static void DeleteFolder(string dir) + { + if (Directory.Exists(dir)) //如果存在这个文件夹删除之 + { + foreach (string d in Directory.GetFileSystemEntries(dir)) + { + if (File.Exists(d)) + File.Delete(d); //直接删除其中的文件 + else + DeleteFolder(d); //递归删除子文件夹 + } + Directory.Delete(dir); //删除已空文件夹 + } + + } + #endregion + + #region 将指定文件夹下面的所有内容copy到目标文件夹下面 果目标文件夹为只读属性就会报错。 + /**************************************** + * 函数名称:CopyDir + * 功能说明:将指定文件夹下面的所有内容copy到目标文件夹下面 果目标文件夹为只读属性就会报错。 + * 参 数:srcPath:原始路径,aimPath:目标文件夹 + * 调用示列: + * string srcPath = Server.MapPath("test/"); + * string aimPath = Server.MapPath("test1/"); + * EC.FileObj.CopyDir(srcPath,aimPath); + *****************************************/ + /// + /// 指定文件夹下面的所有内容copy到目标文件夹下面 + /// + /// 原始路径 + /// 目标文件夹 + public static void CopyDir(string srcPath, string aimPath) + { + try + { + // 检查目标目录是否以目录分割字符结束如果不是则添加之 + if (aimPath[aimPath.Length - 1] != Path.DirectorySeparatorChar) + aimPath += Path.DirectorySeparatorChar; + // 判断目标目录是否存在如果不存在则新建之 + if (!Directory.Exists(aimPath)) + Directory.CreateDirectory(aimPath); + // 得到源目录的文件列表,该里面是包含文件以及目录路径的一个数组 + //如果你指向copy目标文件下面的文件而不包含目录请使用下面的方法 + //string[] fileList = Directory.GetFiles(srcPath); + string[] fileList = Directory.GetFileSystemEntries(srcPath); + //遍历所有的文件和目录 + foreach (string file in fileList) + { + //先当作目录处理如果存在这个目录就递归Copy该目录下面的文件 + + if (Directory.Exists(file)) + CopyDir(file, aimPath + Path.GetFileName(file)); + //否则直接Copy文件 + else + File.Copy(file, aimPath + Path.GetFileName(file), true); + } + + } + catch (Exception ee) + { + throw new Exception(ee.ToString()); + } + } + #endregion + + /// + /// 获取目录下全部文件名 + /// + /// + /// + /// + public static List GetAllFileNames(string path, string pattern = "*") + { + List folder = new DirectoryInfo(path).GetFiles(pattern).ToList(); + + return folder.Select(x => x.Name).ToList(); + } + /// + /// 文件内容替换 + /// + public static string FileContentReplace(string path, string oldStr, string newStr) + { + var content = File.ReadAllText(path); + + if (content.Contains(oldStr)) + { + File.Delete(path); + File.WriteAllText(path, content.Replace(oldStr, newStr)); + } + + return path; + } + /// + /// 文件名称 + /// + public static string FileNameReplace(string path, string oldStr, string newStr) + { + string fileName = Path.GetFileName(path); + if (!fileName.Contains(oldStr)) + { + return path; + } + + string? directoryName = Path.GetDirectoryName(path); + string newFileName = fileName.Replace(oldStr, newStr); + string newPath = Path.Combine(directoryName ?? "", newFileName); + File.Move(path, newPath); + + return newPath; + } + /// + /// 目录名替换 + /// + public static string DirectoryNameReplace(string path, string oldStr, string newStr) + { + string fileName = Path.GetFileName(path); + if (!fileName.Contains(oldStr)) + { + return path; + } + + string? directoryName = Path.GetDirectoryName(path); + string newFileName = fileName.Replace(oldStr, newStr); + string newPath = Path.Combine(directoryName ?? "", newFileName); + Directory.Move(path, newPath); + return newPath; + } + + /// + /// 全部信息递归替换 + /// + /// + /// + /// + public static void AllInfoReplace(string dirPath, string oldStr, string newStr) + { + var path = DirectoryNameReplace(dirPath, oldStr, newStr); + var dirInfo = new DirectoryInfo(path); + var files = dirInfo.GetFiles(); + var dirs = dirInfo.GetDirectories(); + if (files.Length > 0) + { + foreach (var f in files) + { + FileContentReplace(f.FullName, oldStr, newStr); + FileNameReplace(f.FullName, oldStr, newStr); + } + } + if (dirs.Length > 0) + { + foreach (var d in dirs) + { + AllInfoReplace(d.FullName, oldStr, newStr); + } + } + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/HtmlHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/HtmlHelper.cs new file mode 100644 index 00000000..857de345 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/HtmlHelper.cs @@ -0,0 +1,24 @@ +namespace Yi.Framework.Core.Helper +{ + public static class HtmlHelper + { + #region 去除富文本中的HTML标签 + /// + /// 去除富文本中的HTML标签 + /// + /// + /// + /// + public static string ReplaceHtmlTag(string html, int length = 0) + { + string strText = System.Text.RegularExpressions.Regex.Replace(html, "<[^>]+>", ""); + strText = System.Text.RegularExpressions.Regex.Replace(strText, "&[^;]+;", ""); + + if (length > 0 && strText.Length > length) + return strText.Substring(0, length); + + return strText; + } + #endregion + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/HttpHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/HttpHelper.cs new file mode 100644 index 00000000..eb37c1ae --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/HttpHelper.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Mime; +using System.Text; +using System.Text.Json; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Helper +{ + public static class HttpHelper + { + + public static HttpClient Client { get; set; } = new HttpClient(); + + public static async Task Get(string url) + { + return await Client.GetStringAsync(url); + } + + public static async Task GetIO(string url) + { + return await Client.GetStreamAsync(url); + } + + + public static async Task Post(string url, object? item = null, Dictionary? head = null) + { + + using StringContent json = new(JsonSerializer.Serialize(item), Encoding.UTF8, MediaTypeNames.Application.Json); + + + if (head is not null) + { + foreach (var d in head) + { + json.Headers.Add(d.Key, d.Value); + } + } + + var httpResponse = await Client.PostAsync(url, json); + + httpResponse.EnsureSuccessStatusCode(); + + var content = httpResponse.Content; + + return await content.ReadAsStringAsync(); + } + + +// public static string HttpGet(string Url, string postDataStr="") +// { +//#pragma warning disable SYSLIB0014 // 类型或成员已过时 +// HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr); +//#pragma warning restore SYSLIB0014 // 类型或成员已过时 +// request.Method = "GET"; +// request.ContentType = "text/html;charset=UTF-8"; + +// HttpWebResponse response = (HttpWebResponse)request.GetResponse(); +// Stream myResponseStream = response.GetResponseStream(); +// StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8")); +// string retString = myStreamReader.ReadToEnd(); +// myStreamReader.Close(); +// myResponseStream.Close(); + +// return retString; +// } + +// public static bool HttpIOGet(string Url, string file, string postDataStr="") +// { +// HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr); +// request.Method = "GET"; +// request.ContentType = "text/html;charset=UTF-8"; + +// HttpWebResponse response = (HttpWebResponse)request.GetResponse(); +// Stream myResponseStream = response.GetResponseStream(); +// FileStream writer = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Write); +// byte[] buffer = new byte[1024]; +// int c; +// while ((c = myResponseStream.Read(buffer, 0, buffer.Length)) > 0) +// { +// writer.Write(buffer, 0, c); +// } +// writer.Close(); +// myResponseStream.Close(); + +// return true; +// } + +// public static string HttpPost(string Url, string postDataStr="") +// { +// CookieContainer cookie = new CookieContainer(); +//#pragma warning disable SYSLIB0014 // 类型或成员已过时 +// HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url); +//#pragma warning restore SYSLIB0014 // 类型或成员已过时 +// request.Method = "POST"; +// request.ContentType = "application/x-www-form-urlencoded"; +// request.ContentLength = Encoding.UTF8.GetByteCount(postDataStr); +// request.CookieContainer = cookie; + +// Stream myRequestStream = request.GetRequestStream(); +// StreamWriter myStreamWriter = new StreamWriter(myRequestStream, Encoding.GetEncoding("gb2312")); +// myStreamWriter.Write(postDataStr); +// myStreamWriter.Close(); + +// HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + +// response.Cookies = cookie.GetCookies(response.ResponseUri); +// Stream myResponseStream = response.GetResponseStream(); +// StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8")); +// string retString = myStreamReader.ReadToEnd(); +// myStreamReader.Close(); +// myResponseStream.Close(); + +// return retString; +// } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/IdHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/IdHelper.cs new file mode 100644 index 00000000..ca1ad53d --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/IdHelper.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Helper +{ + public static class IdHelper + { + public static dynamic[] ToDynamicArray(this IEnumerable ids) + { + return ids.Select(id => (dynamic)id).ToArray(); + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/IpHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/IpHelper.cs new file mode 100644 index 00000000..60a4fdd7 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/IpHelper.cs @@ -0,0 +1,56 @@ +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; + +namespace Yi.Framework.Core.Helper +{ + public class IpHelper + { + /// + /// 获取当前IP地址 + /// + /// + /// + public static string GetCurrentIp(string preferredNetworks) + { + var instanceIp = "127.0.0.1"; + + try + { + // 获取可用网卡 + var nics = NetworkInterface.GetAllNetworkInterfaces()?.Where(network => network.OperationalStatus == OperationalStatus.Up); + + // 获取所有可用网卡IP信息 + var ipCollection = nics?.Select(x => x.GetIPProperties())?.SelectMany(x => x.UnicastAddresses); + + if (ipCollection is null) + { + return instanceIp; + } + + foreach (var ipadd in ipCollection) + { + if (!IPAddress.IsLoopback(ipadd.Address) && ipadd.Address.AddressFamily == AddressFamily.InterNetwork) + { + if (string.IsNullOrEmpty(preferredNetworks)) + { + instanceIp = ipadd.Address.ToString(); + break; + } + + if (!ipadd.Address.ToString().StartsWith(preferredNetworks)) continue; + instanceIp = ipadd.Address.ToString(); + break; + } + } + } + catch + { + // ignored + } + + return instanceIp; + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/JsonHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/JsonHelper.cs new file mode 100644 index 00000000..5b06a2ea --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/JsonHelper.cs @@ -0,0 +1,509 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace Yi.Framework.Core.Helper +{ + public class JsonHelper + { + + + public static string ObjToStr(T obj) + { + return Newtonsoft.Json.JsonConvert.SerializeObject(obj); + } + + public static T StrToObj(string str) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(str)!; + } + /// + /// 转换对象为JSON格式数据 + /// + /// + /// 对象 + /// 字符格式的JSON数据 + public static string GetJSON(object obj) + { + string result = String.Empty; + try + { + JsonSerializer.Serialize(""); + System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = + new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T)); + using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) + { + serializer.WriteObject(ms, obj); + result = System.Text.Encoding.UTF8.GetString(ms.ToArray()); + } + } + catch (Exception) + { + throw; + } + return result; + } + /// + /// 转换List的数据为JSON格式 + /// + /// + /// 列表值 + /// JSON格式数据 + public string JSON(List vals) + { + System.Text.StringBuilder st = new System.Text.StringBuilder(); + try + { + System.Runtime.Serialization.Json.DataContractJsonSerializer s = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T)); + + foreach (T city in vals) + { + using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) + { + s.WriteObject(ms, city); + st.Append(System.Text.Encoding.UTF8.GetString(ms.ToArray())); + } + } + } + catch (Exception) + { + } + + return st.ToString(); + } + /// + /// JSON格式字符转换为T类型的对象 + /// + /// + /// + /// + public static T ParseFormByJson(string jsonStr) + { + T obj = Activator.CreateInstance(); + using (System.IO.MemoryStream ms = + new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(jsonStr))) + { + System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = + new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T)); + return (T)serializer.ReadObject(ms)!; + } + } + + public string JSON1(List vals) + { + System.Text.StringBuilder st = new System.Text.StringBuilder(); + try + { + System.Runtime.Serialization.Json.DataContractJsonSerializer s = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(SendData)); + + foreach (SendData city in vals) + { + using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) + { + s.WriteObject(ms, city); + st.Append(System.Text.Encoding.UTF8.GetString(ms.ToArray())); + } + } + } + catch (Exception) + { + } + + return st.ToString(); + } + + private static bool IsJsonStart(ref string json) + { + if (!string.IsNullOrEmpty(json)) + { + json = json.Trim('\r', '\n', ' '); + if (json.Length > 1) + { + char s = json[0]; + char e = json[json.Length - 1]; + return (s == '{' && e == '}') || (s == '[' && e == ']'); + } + } + return false; + } + public static bool IsJson(string json) + { + int errIndex; + return IsJson(json, out errIndex); + } + public static bool IsJson(string json, out int errIndex) + { + errIndex = 0; + if (IsJsonStart(ref json)) + { + CharState cs = new CharState(); + char c; + for (int i = 0; i < json.Length; i++) + { + c = json[i]; + if (SetCharState(c, ref cs) && cs.childrenStart)//设置关键符号状态。 + { + string item = json.Substring(i); + int err; + int length = GetValueLength(item, true, out err); + cs.childrenStart = false; + if (err > 0) + { + errIndex = i + err; + return false; + } + i = i + length - 1; + } + if (cs.isError) + { + errIndex = i; + return false; + } + } + + return !cs.arrayStart && !cs.jsonStart; + } + return false; + } + + /// + /// 获取值的长度(当Json值嵌套以"{"或"["开头时) + /// + private static int GetValueLength(string json, bool breakOnErr, out int errIndex) + { + errIndex = 0; + int len = 0; + if (!string.IsNullOrEmpty(json)) + { + CharState cs = new CharState(); + char c; + for (int i = 0; i < json.Length; i++) + { + c = json[i]; + if (!SetCharState(c, ref cs))//设置关键符号状态。 + { + if (!cs.jsonStart && !cs.arrayStart)//json结束,又不是数组,则退出。 + { + break; + } + } + else if (cs.childrenStart)//正常字符,值状态下。 + { + int length = GetValueLength(json.Substring(i), breakOnErr, out errIndex);//递归子值,返回一个长度。。。 + cs.childrenStart = false; + cs.valueStart = 0; + //cs.state = 0; + i = i + length - 1; + } + if (breakOnErr && cs.isError) + { + errIndex = i; + return i; + } + if (!cs.jsonStart && !cs.arrayStart)//记录当前结束位置。 + { + len = i + 1;//长度比索引+1 + break; + } + } + } + return len; + } + + /// + /// 设置字符状态(返回true则为关键词,返回false则当为普通字符处理) + /// + private static bool SetCharState(char c, ref CharState cs) + { + cs.CheckIsError(c); + switch (c) + { + case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}] + #region 大括号 + if (cs.keyStart <= 0 && cs.valueStart <= 0) + { + cs.keyStart = 0; + cs.valueStart = 0; + if (cs.jsonStart && cs.state == 1) + { + cs.childrenStart = true; + } + else + { + cs.state = 0; + } + cs.jsonStart = true;//开始。 + return true; + } + #endregion + break; + case '}': + #region 大括号结束 + if (cs.keyStart <= 0 && cs.valueStart < 2 && cs.jsonStart) + { + cs.jsonStart = false;//正常结束。 + cs.state = 0; + cs.keyStart = 0; + cs.valueStart = 0; + cs.setDicValue = true; + return true; + } + // cs.isError = !cs.jsonStart && cs.state == 0; + #endregion + break; + case '[': + #region 中括号开始 + if (!cs.jsonStart) + { + cs.arrayStart = true; + return true; + } + else if (cs.jsonStart && cs.state == 1) + { + cs.childrenStart = true; + return true; + } + #endregion + break; + case ']': + #region 中括号结束 + if (cs.arrayStart && !cs.jsonStart && cs.keyStart <= 2 && cs.valueStart <= 0)//[{},333]//这样结束。 + { + cs.keyStart = 0; + cs.valueStart = 0; + cs.arrayStart = false; + return true; + } + #endregion + break; + case '"': + case '\'': + #region 引号 + if (cs.jsonStart || cs.arrayStart) + { + if (cs.state == 0)//key阶段,有可能是数组["aa",{}] + { + if (cs.keyStart <= 0) + { + cs.keyStart = (c == '"' ? 3 : 2); + return true; + } + else if ((cs.keyStart == 2 && c == '\'') || (cs.keyStart == 3 && c == '"')) + { + if (!cs.escapeChar) + { + cs.keyStart = -1; + return true; + } + else + { + cs.escapeChar = false; + } + } + } + else if (cs.state == 1 && cs.jsonStart)//值阶段必须是Json开始了。 + { + if (cs.valueStart <= 0) + { + cs.valueStart = (c == '"' ? 3 : 2); + return true; + } + else if ((cs.valueStart == 2 && c == '\'') || (cs.valueStart == 3 && c == '"')) + { + if (!cs.escapeChar) + { + cs.valueStart = -1; + return true; + } + else + { + cs.escapeChar = false; + } + } + + } + } + #endregion + break; + case ':': + #region 冒号 + if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0) + { + if (cs.keyStart == 1) + { + cs.keyStart = -1; + } + cs.state = 1; + return true; + } + // cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1); + #endregion + break; + case ',': + #region 逗号 //["aa",{aa:12,}] + + if (cs.jsonStart) + { + if (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1) + { + cs.state = 0; + cs.keyStart = 0; + cs.valueStart = 0; + //if (cs.valueStart == 1) + //{ + // cs.valueStart = 0; + //} + cs.setDicValue = true; + return true; + } + } + else if (cs.arrayStart && cs.keyStart <= 2) + { + cs.keyStart = 0; + //if (cs.keyStart == 1) + //{ + // cs.keyStart = -1; + //} + return true; + } + #endregion + break; + case ' ': + case '\r': + case '\n'://[ "a",\r\n{} ] + case '\0': + case '\t': + if (cs.keyStart <= 0 && cs.valueStart <= 0) //cs.jsonStart && + { + return true;//跳过空格。 + } + break; + default: //值开头。。 + if (c == '\\') //转义符号 + { + if (cs.escapeChar) + { + cs.escapeChar = false; + } + else + { + cs.escapeChar = true; + return true; + } + } + else + { + cs.escapeChar = false; + } + if (cs.jsonStart || cs.arrayStart) // Json 或数组开始了。 + { + if (cs.keyStart <= 0 && cs.state == 0) + { + cs.keyStart = 1;//无引号的 + } + else if (cs.valueStart <= 0 && cs.state == 1 && cs.jsonStart)//只有Json开始才有值。 + { + cs.valueStart = 1;//无引号的 + } + } + break; + } + return false; + } + } + /// + /// 字符状态 + /// + public class CharState + { + internal bool jsonStart = false;//以 "{"开始了... + internal bool setDicValue = false;// 可以设置字典值了。 + internal bool escapeChar = false;//以"\"转义符号开始了 + /// + /// 数组开始【仅第一开头才算】,值嵌套的以【childrenStart】来标识。 + /// + internal bool arrayStart = false;//以"[" 符号开始了 + internal bool childrenStart = false;//子级嵌套开始了。 + /// + /// 【0 初始状态,或 遇到“,”逗号】;【1 遇到“:”冒号】 + /// + internal int state = 0; + + /// + /// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】 + /// + internal int keyStart = 0; + /// + /// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】 + /// + internal int valueStart = 0; + internal bool isError = false;//是否语法错误。 + + internal void CheckIsError(char c)//只当成一级处理(因为GetLength会递归到每一个子项处理) + { + if (keyStart > 1 || valueStart > 1) + { + return; + } + //示例 ["aa",{"bbbb":123,"fff","ddd"}] + switch (c) + { + case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}] + isError = jsonStart && state == 0;//重复开始错误 同时不是值处理。 + break; + case '}': + isError = !jsonStart || (keyStart != 0 && state == 0);//重复结束错误 或者 提前结束{"aa"}。正常的有{} + break; + case '[': + isError = arrayStart && state == 0;//重复开始错误 + break; + case ']': + isError = !arrayStart || jsonStart;//重复开始错误 或者 Json 未结束 + break; + case '"': + case '\'': + isError = !(jsonStart || arrayStart); //json 或数组开始。 + if (!isError) + { + //重复开始 [""",{"" "}] + isError = (state == 0 && keyStart == -1) || (state == 1 && valueStart == -1); + } + if (!isError && arrayStart && !jsonStart && c == '\'')//['aa',{}] + { + isError = true; + } + break; + case ':': + isError = !jsonStart || state == 1;//重复出现。 + break; + case ',': + isError = !(jsonStart || arrayStart); //json 或数组开始。 + if (!isError) + { + if (jsonStart) + { + isError = state == 0 || (state == 1 && valueStart > 1);//重复出现。 + } + else if (arrayStart)//["aa,] [,] [{},{}] + { + isError = keyStart == 0 && !setDicValue; + } + } + break; + case ' ': + case '\r': + case '\n'://[ "a",\r\n{} ] + case '\0': + case '\t': + break; + default: //值开头。。 + isError = (!jsonStart && !arrayStart) || (state == 0 && keyStart == -1) || (valueStart == -1 && state == 1);// + break; + } + //if (isError) + //{ + + //} + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/MD5Hepler.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/MD5Hepler.cs new file mode 100644 index 00000000..c7f4c1f2 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/MD5Hepler.cs @@ -0,0 +1,132 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Yi.Framework.Core.Helper +{ + public class MD5Helper + { + /// + /// 生成PasswordSalt + /// + /// 返回string + public static string GenerateSalt() + { + byte[] buf = new byte[16]; +#pragma warning disable SYSLIB0023 // 类型或成员已过时 + (new RNGCryptoServiceProvider()).GetBytes(buf); +#pragma warning restore SYSLIB0023 // 类型或成员已过时 + return Convert.ToBase64String(buf); + } + + /// + /// 加密密码 + /// + /// 密码 + /// 加密类型 + /// PasswordSalt + /// 加密后的密码 + public static string SHA2Encode(string pass, string salt, int passwordFormat = 1) + { + if (passwordFormat == 0) // MembershipPasswordFormat.Clear + return pass; + + byte[] bIn = Encoding.Unicode.GetBytes(pass); + byte[] bSalt = Convert.FromBase64String(salt); + byte[] bAll = new byte[bSalt.Length + bIn.Length]; + byte[]? bRet = null; + + Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length); + Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length); + +#pragma warning disable SYSLIB0021 // 类型或成员已过时 + var s = SHA512Managed.Create(); +#pragma warning restore SYSLIB0021 // 类型或成员已过时 + bRet = s.ComputeHash(bAll); + + return ConvertEx.ToUrlBase64String(bRet); + } + + /// + /// 16位MD5加密 + /// + /// + /// + public static string MD5Encrypt16(string password) + { + var md5 = MD5.Create(); + string t2 = BitConverter.ToString(md5.ComputeHash(Encoding.Default.GetBytes(password)), 4, 8); + t2 = t2.Replace("-", string.Empty); + return t2; + } + + /// + /// 32位MD5加密 + /// + /// + /// + public static string MD5Encrypt32(string password = "") + { + string pwd = string.Empty; + try + { + if (!string.IsNullOrEmpty(password) && !string.IsNullOrWhiteSpace(password)) + { + MD5 md5 = MD5.Create(); //实例化一个md5对像 + // 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择  + byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(password)); + // 通过使用循环,将字节类型的数组转换为字符串,此字符串是常规字符格式化所得 + foreach (var item in s) + { + // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母,如果使用大写(X)则格式后的字符是大写字符 + pwd = string.Concat(pwd, item.ToString("X2")); + } + } + } + catch + { + throw new Exception($"错误的 password 字符串:【{password}】"); + } + return pwd; + } + + /// + /// 64位MD5加密 + /// + /// + /// + public static string MD5Encrypt64(string password) + { + // 实例化一个md5对像 + // 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择  + MD5 md5 = MD5.Create(); + byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(password)); + return Convert.ToBase64String(s); + } + } + public class ConvertEx + { + static readonly char[] padding = { '=' }; + public static string ToUrlBase64String(byte[] inArray) + { + var str = Convert.ToBase64String(inArray); + str = str.TrimEnd(padding).Replace('+', '-').Replace('/', '_'); + + return str; + } + + public static byte[] FromUrlBase64String(string s) + { + string incoming = s.Replace('_', '/').Replace('-', '+'); + switch (s.Length % 4) + { + case 2: incoming += "=="; break; + case 3: incoming += "="; break; + } + byte[] bytes = Convert.FromBase64String(incoming); + + return bytes; + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/MimeHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/MimeHelper.cs new file mode 100644 index 00000000..ca0e7c05 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/MimeHelper.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Helper +{ + public static class MimeHelper + { + // 通过自己定义一个静态类 + // 将所有的Content Type都扔进去吧 + // 调用的时候直接调用静态方法即可。 + + private static Hashtable _mimeMappingTable; + + private static void AddMimeMapping(string extension, string MimeType) + { + MimeHelper._mimeMappingTable.Add(extension, MimeType); + } + + public static string GetMimeMapping(string FileName) + { + string text = null!; + int num = FileName.LastIndexOf('.'); + if (0 < num && num > FileName.LastIndexOf('\\')) + { + text = (string)MimeHelper._mimeMappingTable[FileName.Substring(num)]!; + } + if (text == null) + { + text = (string)MimeHelper._mimeMappingTable[".*"]!; + } + return text; + } + + static MimeHelper() + { + MimeHelper._mimeMappingTable = new Hashtable(190, StringComparer.CurrentCultureIgnoreCase); + MimeHelper.AddMimeMapping(".323", "text/h323"); + MimeHelper.AddMimeMapping(".asx", "video/x-ms-asf"); + MimeHelper.AddMimeMapping(".acx", "application/internet-property-stream"); + MimeHelper.AddMimeMapping(".ai", "application/postscript"); + MimeHelper.AddMimeMapping(".aif", "audio/x-aiff"); + MimeHelper.AddMimeMapping(".aiff", "audio/aiff"); + MimeHelper.AddMimeMapping(".axs", "application/olescript"); + MimeHelper.AddMimeMapping(".aifc", "audio/aiff"); + MimeHelper.AddMimeMapping(".asr", "video/x-ms-asf"); + MimeHelper.AddMimeMapping(".avi", "video/x-msvideo"); + MimeHelper.AddMimeMapping(".asf", "video/x-ms-asf"); + MimeHelper.AddMimeMapping(".au", "audio/basic"); + MimeHelper.AddMimeMapping(".application", "application/x-ms-application"); + MimeHelper.AddMimeMapping(".bin", "application/octet-stream"); + MimeHelper.AddMimeMapping(".bas", "text/plain"); + MimeHelper.AddMimeMapping(".bcpio", "application/x-bcpio"); + MimeHelper.AddMimeMapping(".bmp", "image/bmp"); + MimeHelper.AddMimeMapping(".cdf", "application/x-cdf"); + MimeHelper.AddMimeMapping(".cat", "application/vndms-pkiseccat"); + MimeHelper.AddMimeMapping(".crt", "application/x-x509-ca-cert"); + MimeHelper.AddMimeMapping(".c", "text/plain"); + MimeHelper.AddMimeMapping(".css", "text/css"); + MimeHelper.AddMimeMapping(".cer", "application/x-x509-ca-cert"); + MimeHelper.AddMimeMapping(".crl", "application/pkix-crl"); + MimeHelper.AddMimeMapping(".cmx", "image/x-cmx"); + MimeHelper.AddMimeMapping(".csh", "application/x-csh"); + MimeHelper.AddMimeMapping(".cod", "image/cis-cod"); + MimeHelper.AddMimeMapping(".cpio", "application/x-cpio"); + MimeHelper.AddMimeMapping(".clp", "application/x-msclip"); + MimeHelper.AddMimeMapping(".crd", "application/x-mscardfile"); + MimeHelper.AddMimeMapping(".deploy", "application/octet-stream"); + MimeHelper.AddMimeMapping(".dll", "application/x-msdownload"); + MimeHelper.AddMimeMapping(".dot", "application/msword"); + MimeHelper.AddMimeMapping(".doc", "application/msword"); + MimeHelper.AddMimeMapping(".dvi", "application/x-dvi"); + MimeHelper.AddMimeMapping(".dir", "application/x-director"); + MimeHelper.AddMimeMapping(".dxr", "application/x-director"); + MimeHelper.AddMimeMapping(".der", "application/x-x509-ca-cert"); + MimeHelper.AddMimeMapping(".dib", "image/bmp"); + MimeHelper.AddMimeMapping(".dcr", "application/x-director"); + MimeHelper.AddMimeMapping(".disco", "text/xml"); + MimeHelper.AddMimeMapping(".exe", "application/octet-stream"); + MimeHelper.AddMimeMapping(".etx", "text/x-setext"); + MimeHelper.AddMimeMapping(".evy", "application/envoy"); + MimeHelper.AddMimeMapping(".eml", "message/rfc822"); + MimeHelper.AddMimeMapping(".eps", "application/postscript"); + MimeHelper.AddMimeMapping(".flr", "x-world/x-vrml"); + MimeHelper.AddMimeMapping(".fif", "application/fractals"); + MimeHelper.AddMimeMapping(".gtar", "application/x-gtar"); + MimeHelper.AddMimeMapping(".gif", "image/gif"); + MimeHelper.AddMimeMapping(".gz", "application/x-gzip"); + MimeHelper.AddMimeMapping(".hta", "application/hta"); + MimeHelper.AddMimeMapping(".htc", "text/x-component"); + MimeHelper.AddMimeMapping(".htt", "text/webviewhtml"); + MimeHelper.AddMimeMapping(".h", "text/plain"); + MimeHelper.AddMimeMapping(".hdf", "application/x-hdf"); + MimeHelper.AddMimeMapping(".hlp", "application/winhlp"); + MimeHelper.AddMimeMapping(".html", "text/html"); + MimeHelper.AddMimeMapping(".htm", "text/html"); + MimeHelper.AddMimeMapping(".hqx", "application/mac-binhex40"); + MimeHelper.AddMimeMapping(".isp", "application/x-internet-signup"); + MimeHelper.AddMimeMapping(".iii", "application/x-iphone"); + MimeHelper.AddMimeMapping(".ief", "image/ief"); + MimeHelper.AddMimeMapping(".ivf", "video/x-ivf"); + MimeHelper.AddMimeMapping(".ins", "application/x-internet-signup"); + MimeHelper.AddMimeMapping(".ico", "image/x-icon"); + MimeHelper.AddMimeMapping(".jpg", "image/jpeg"); + MimeHelper.AddMimeMapping(".jfif", "image/pjpeg"); + MimeHelper.AddMimeMapping(".jpe", "image/jpeg"); + MimeHelper.AddMimeMapping(".jpeg", "image/jpeg"); + MimeHelper.AddMimeMapping(".js", "application/x-javascript"); + MimeHelper.AddMimeMapping(".lsx", "video/x-la-asf"); + MimeHelper.AddMimeMapping(".latex", "application/x-latex"); + MimeHelper.AddMimeMapping(".lsf", "video/x-la-asf"); + MimeHelper.AddMimeMapping(".manifest", "application/x-ms-manifest"); + MimeHelper.AddMimeMapping(".mhtml", "message/rfc822"); + MimeHelper.AddMimeMapping(".mny", "application/x-msmoney"); + MimeHelper.AddMimeMapping(".mht", "message/rfc822"); + MimeHelper.AddMimeMapping(".mid", "audio/mid"); + MimeHelper.AddMimeMapping(".mpv2", "video/mpeg"); + MimeHelper.AddMimeMapping(".man", "application/x-troff-man"); + MimeHelper.AddMimeMapping(".mvb", "application/x-msmediaview"); + MimeHelper.AddMimeMapping(".mpeg", "video/mpeg"); + MimeHelper.AddMimeMapping(".m3u", "audio/x-mpegurl"); + MimeHelper.AddMimeMapping(".mdb", "application/x-msaccess"); + MimeHelper.AddMimeMapping(".mpp", "application/vnd.ms-project"); + MimeHelper.AddMimeMapping(".m1v", "video/mpeg"); + MimeHelper.AddMimeMapping(".mpa", "video/mpeg"); + MimeHelper.AddMimeMapping(".me", "application/x-troff-me"); + MimeHelper.AddMimeMapping(".m13", "application/x-msmediaview"); + MimeHelper.AddMimeMapping(".movie", "video/x-sgi-movie"); + MimeHelper.AddMimeMapping(".m14", "application/x-msmediaview"); + MimeHelper.AddMimeMapping(".mpe", "video/mpeg"); + MimeHelper.AddMimeMapping(".mp2", "video/mpeg"); + MimeHelper.AddMimeMapping(".mov", "video/quicktime"); + MimeHelper.AddMimeMapping(".mp3", "audio/mpeg"); + MimeHelper.AddMimeMapping(".mpg", "video/mpeg"); + MimeHelper.AddMimeMapping(".ms", "application/x-troff-ms"); + MimeHelper.AddMimeMapping(".nc", "application/x-netcdf"); + MimeHelper.AddMimeMapping(".nws", "message/rfc822"); + MimeHelper.AddMimeMapping(".oda", "application/oda"); + MimeHelper.AddMimeMapping(".ods", "application/oleobject"); + MimeHelper.AddMimeMapping(".pmc", "application/x-perfmon"); + MimeHelper.AddMimeMapping(".p7r", "application/x-pkcs7-certreqresp"); + MimeHelper.AddMimeMapping(".p7b", "application/x-pkcs7-certificates"); + MimeHelper.AddMimeMapping(".p7s", "application/pkcs7-signature"); + MimeHelper.AddMimeMapping(".pmw", "application/x-perfmon"); + MimeHelper.AddMimeMapping(".ps", "application/postscript"); + MimeHelper.AddMimeMapping(".p7c", "application/pkcs7-mime"); + MimeHelper.AddMimeMapping(".pbm", "image/x-portable-bitmap"); + MimeHelper.AddMimeMapping(".ppm", "image/x-portable-pixmap"); + MimeHelper.AddMimeMapping(".pub", "application/x-mspublisher"); + MimeHelper.AddMimeMapping(".pnm", "image/x-portable-anymap"); + MimeHelper.AddMimeMapping(".png", "image/png"); + MimeHelper.AddMimeMapping(".pml", "application/x-perfmon"); + MimeHelper.AddMimeMapping(".p10", "application/pkcs10"); + MimeHelper.AddMimeMapping(".pfx", "application/x-pkcs12"); + MimeHelper.AddMimeMapping(".p12", "application/x-pkcs12"); + MimeHelper.AddMimeMapping(".pdf", "application/pdf"); + MimeHelper.AddMimeMapping(".pps", "application/vnd.ms-powerpoint"); + MimeHelper.AddMimeMapping(".p7m", "application/pkcs7-mime"); + MimeHelper.AddMimeMapping(".pko", "application/vndms-pkipko"); + MimeHelper.AddMimeMapping(".ppt", "application/vnd.ms-powerpoint"); + MimeHelper.AddMimeMapping(".pmr", "application/x-perfmon"); + MimeHelper.AddMimeMapping(".pma", "application/x-perfmon"); + MimeHelper.AddMimeMapping(".pot", "application/vnd.ms-powerpoint"); + MimeHelper.AddMimeMapping(".prf", "application/pics-rules"); + MimeHelper.AddMimeMapping(".pgm", "image/x-portable-graymap"); + MimeHelper.AddMimeMapping(".qt", "video/quicktime"); + MimeHelper.AddMimeMapping(".ra", "audio/x-pn-realaudio"); + MimeHelper.AddMimeMapping(".rgb", "image/x-rgb"); + MimeHelper.AddMimeMapping(".ram", "audio/x-pn-realaudio"); + MimeHelper.AddMimeMapping(".rmi", "audio/mid"); + MimeHelper.AddMimeMapping(".ras", "image/x-cmu-raster"); + MimeHelper.AddMimeMapping(".roff", "application/x-troff"); + MimeHelper.AddMimeMapping(".rtf", "application/rtf"); + MimeHelper.AddMimeMapping(".rtx", "text/richtext"); + MimeHelper.AddMimeMapping(".sv4crc", "application/x-sv4crc"); + MimeHelper.AddMimeMapping(".spc", "application/x-pkcs7-certificates"); + MimeHelper.AddMimeMapping(".setreg", "application/set-registration-initiation"); + MimeHelper.AddMimeMapping(".snd", "audio/basic"); + MimeHelper.AddMimeMapping(".stl", "application/vndms-pkistl"); + MimeHelper.AddMimeMapping(".setpay", "application/set-payment-initiation"); + MimeHelper.AddMimeMapping(".stm", "text/html"); + MimeHelper.AddMimeMapping(".shar", "application/x-shar"); + MimeHelper.AddMimeMapping(".sh", "application/x-sh"); + MimeHelper.AddMimeMapping(".sit", "application/x-stuffit"); + MimeHelper.AddMimeMapping(".spl", "application/futuresplash"); + MimeHelper.AddMimeMapping(".sct", "text/scriptlet"); + MimeHelper.AddMimeMapping(".scd", "application/x-msschedule"); + MimeHelper.AddMimeMapping(".sst", "application/vndms-pkicertstore"); + MimeHelper.AddMimeMapping(".src", "application/x-wais-source"); + MimeHelper.AddMimeMapping(".sv4cpio", "application/x-sv4cpio"); + MimeHelper.AddMimeMapping(".tex", "application/x-tex"); + MimeHelper.AddMimeMapping(".tgz", "application/x-compressed"); + MimeHelper.AddMimeMapping(".t", "application/x-troff"); + MimeHelper.AddMimeMapping(".tar", "application/x-tar"); + MimeHelper.AddMimeMapping(".tr", "application/x-troff"); + MimeHelper.AddMimeMapping(".tif", "image/tiff"); + MimeHelper.AddMimeMapping(".txt", "text/plain"); + MimeHelper.AddMimeMapping(".texinfo", "application/x-texinfo"); + MimeHelper.AddMimeMapping(".trm", "application/x-msterminal"); + MimeHelper.AddMimeMapping(".tiff", "image/tiff"); + MimeHelper.AddMimeMapping(".tcl", "application/x-tcl"); + MimeHelper.AddMimeMapping(".texi", "application/x-texinfo"); + MimeHelper.AddMimeMapping(".tsv", "text/tab-separated-values"); + MimeHelper.AddMimeMapping(".ustar", "application/x-ustar"); + MimeHelper.AddMimeMapping(".uls", "text/iuls"); + MimeHelper.AddMimeMapping(".vcf", "text/x-vcard"); + MimeHelper.AddMimeMapping(".wps", "application/vnd.ms-works"); + MimeHelper.AddMimeMapping(".wav", "audio/wav"); + MimeHelper.AddMimeMapping(".wrz", "x-world/x-vrml"); + MimeHelper.AddMimeMapping(".wri", "application/x-mswrite"); + MimeHelper.AddMimeMapping(".wks", "application/vnd.ms-works"); + MimeHelper.AddMimeMapping(".wmf", "application/x-msmetafile"); + MimeHelper.AddMimeMapping(".wcm", "application/vnd.ms-works"); + MimeHelper.AddMimeMapping(".wrl", "x-world/x-vrml"); + MimeHelper.AddMimeMapping(".wdb", "application/vnd.ms-works"); + MimeHelper.AddMimeMapping(".wsdl", "text/xml"); + MimeHelper.AddMimeMapping(".xap", "application/x-silverlight-app"); + MimeHelper.AddMimeMapping(".xml", "text/xml"); + MimeHelper.AddMimeMapping(".xlm", "application/vnd.ms-excel"); + MimeHelper.AddMimeMapping(".xaf", "x-world/x-vrml"); + MimeHelper.AddMimeMapping(".xla", "application/vnd.ms-excel"); + MimeHelper.AddMimeMapping(".xls", "application/vnd.ms-excel"); + MimeHelper.AddMimeMapping(".xlsx", "application/vnd.ms-excel"); + MimeHelper.AddMimeMapping(".xof", "x-world/x-vrml"); + MimeHelper.AddMimeMapping(".xlt", "application/vnd.ms-excel"); + MimeHelper.AddMimeMapping(".xlc", "application/vnd.ms-excel"); + MimeHelper.AddMimeMapping(".xsl", "text/xml"); + MimeHelper.AddMimeMapping(".xbm", "image/x-xbitmap"); + MimeHelper.AddMimeMapping(".xlw", "application/vnd.ms-excel"); + MimeHelper.AddMimeMapping(".xpm", "image/x-xpixmap"); + MimeHelper.AddMimeMapping(".xwd", "image/x-xwindowdump"); + MimeHelper.AddMimeMapping(".xsd", "text/xml"); + MimeHelper.AddMimeMapping(".z", "application/x-compress"); + MimeHelper.AddMimeMapping(".zip", "application/x-zip-compressed"); + MimeHelper.AddMimeMapping(".*", "application/octet-stream"); + } + } + + + +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/RSAFileHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/RSAFileHelper.cs new file mode 100644 index 00000000..cc873a2c --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/RSAFileHelper.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Helper +{ + public class RSAFileHelper + { + public static RSA GetKey() + { + return GetRSA("key.pem"); + } + public static RSA GetPublicKey() + { + return GetRSA("public.pem"); + } + + private static RSA GetRSA(string fileName) + { + string rootPath = Directory.GetCurrentDirectory(); + string filePath = Path.Combine(rootPath, fileName); + if (!System.IO.File.Exists(filePath)) + throw new Exception("文件不存在"); + string key = System.IO.File.ReadAllText(filePath); + var rsa = RSA.Create(); + rsa.ImportFromPem(key.AsSpan()); + return rsa; + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/RSAHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/RSAHelper.cs new file mode 100644 index 00000000..f2fd6990 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/RSAHelper.cs @@ -0,0 +1,390 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Yi.Framework.Core.Helper +{ + /// + /// RSA加解密 使用OpenSSL的公钥加密/私钥解密 + /// 公私钥请使用openssl生成 + /// + public class RSAHelper + { + public readonly RSA? _privateKeyRsaProvider; + public readonly RSA? _publicKeyRsaProvider; + private readonly HashAlgorithmName _hashAlgorithmName; + private readonly Encoding _encoding; + + /// + /// 实例化RSAHelper + /// + /// 加密算法类型 RSA SHA1;RSA2 SHA256 密钥长度至少为2048 + /// 编码类型 + /// 私钥 + /// 公钥 + public RSAHelper(RSAType rsaType, Encoding encoding, string privateKey, string? publicKey = null) + { + _encoding = encoding; + if (!string.IsNullOrEmpty(privateKey)) + { + _privateKeyRsaProvider = CreateRsaProviderFromPrivateKey(privateKey); + } + + if (!string.IsNullOrEmpty(publicKey)) + { + _publicKeyRsaProvider = CreateRsaProviderFromPublicKey(publicKey); + } + + _hashAlgorithmName = rsaType == RSAType.RSA ? HashAlgorithmName.SHA1 : HashAlgorithmName.SHA256; + } + + #region 使用私钥签名 + + /// + /// 使用私钥签名 + /// + /// 原始数据 + /// + public string Sign(string data) + { + byte[] dataBytes = _encoding.GetBytes(data); + + var signatureBytes = _privateKeyRsaProvider!.SignData(dataBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1); + + return Convert.ToBase64String(signatureBytes); + } + + #endregion + + #region 使用公钥验签 + + /// + /// 使用公钥验签 + /// + /// 原始数据 + /// 签名 + /// + public bool Verify(string data, string sign) + { + byte[] dataBytes = _encoding.GetBytes(data); + byte[] signBytes = Convert.FromBase64String(sign); + + var verify = _publicKeyRsaProvider!.VerifyData(dataBytes, signBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1); + + return verify; + } + + #endregion + + #region 解密 + /// + /// 私钥解密(原) + /// + /// 解密字符串(base64) + /// + + //public string Decrypt(string cipherText) + //{ + // if (_privateKeyRsaProvider == null) + // { + // throw new Exception("_privateKeyRsaProvider is null"); + // } + // return _encoding.GetString(_privateKeyRsaProvider.Decrypt(Convert.FromBase64String(cipherText), RSAEncryptionPadding.Pkcs1)); + //} + /// + /// 私钥解密(支持大量数据) + /// + /// + /// + public string Decrypt(string cipherText) + { + if (_privateKeyRsaProvider == null) + { + throw new Exception("_privateKeyRsaProvider is null"); + } + var bufferSize = (_privateKeyRsaProvider.KeySize / 8); + byte[] buffer = new byte[bufferSize];//待解密块 + using (MemoryStream msInput = new MemoryStream(Convert.FromBase64String(cipherText))) + { + using (MemoryStream msOutput = new MemoryStream()) + { + int readLen; while ((readLen = msInput.Read(buffer, 0, bufferSize)) > 0) + { + byte[] dataToEnc = new byte[readLen]; + Array.Copy(buffer, 0, dataToEnc, 0, readLen); byte[] encData = _privateKeyRsaProvider.Decrypt(dataToEnc, RSAEncryptionPadding.Pkcs1); + msOutput.Write(encData, 0, encData.Length); + } + byte[] result = msOutput.ToArray(); + return _encoding.GetString(result); + } + } + } + + #endregion + + #region 加密 + + /// + /// 公钥加密(原) + /// + /// + /// + //public string Encrypt(string text) + //{ + // if (_publicKeyRsaProvider == null) + // { + // throw new Exception("_publicKeyRsaProvider is null"); + // } + // return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.Pkcs1)); + //} + /// + /// 公钥加密(支持大量数据) + /// + /// + /// + public string Encrypt(string text) + { + if (_publicKeyRsaProvider == null) + { + throw new Exception("_publicKeyRsaProvider is null"); + } + var bufferSize = (_publicKeyRsaProvider.KeySize / 8 - 11); + byte[] buffer = new byte[bufferSize];//待加密块 + + using (MemoryStream msInput = new MemoryStream(_encoding.GetBytes(text))) + { + using (MemoryStream msOutput = new MemoryStream()) + { + int readLen; while ((readLen = msInput.Read(buffer, 0, bufferSize)) > 0) + { + byte[] dataToEnc = new byte[readLen]; + Array.Copy(buffer, 0, dataToEnc, 0, readLen); byte[] encData = _publicKeyRsaProvider.Encrypt(dataToEnc, RSAEncryptionPadding.Pkcs1); + msOutput.Write(encData, 0, encData.Length); + } + byte[] result = msOutput.ToArray(); + return Convert.ToBase64String(result); + } + } + } + + #endregion + + #region 使用私钥创建RSA实例 + /// + /// 使用私钥创建RSA实例 + /// + /// + /// + private RSA CreateRsaProviderFromPrivateKey(string privateKey) + { + var privateKeyBits = Convert.FromBase64String(privateKey); + + var rsa = RSA.Create(); + var rsaParameters = new RSAParameters(); + + using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits))) + { + byte bt = 0; + ushort twobytes = 0; + twobytes = binr.ReadUInt16(); + if (twobytes == 0x8130) + binr.ReadByte(); + else if (twobytes == 0x8230) + binr.ReadInt16(); + else + throw new Exception("Unexpected value read binr.ReadUInt16()"); + + twobytes = binr.ReadUInt16(); + if (twobytes != 0x0102) + throw new Exception("Unexpected version"); + + bt = binr.ReadByte(); + if (bt != 0x00) + throw new Exception("Unexpected value read binr.ReadByte()"); + + rsaParameters.Modulus = binr.ReadBytes(GetIntegerSize(binr)); + rsaParameters.Exponent = binr.ReadBytes(GetIntegerSize(binr)); + rsaParameters.D = binr.ReadBytes(GetIntegerSize(binr)); + rsaParameters.P = binr.ReadBytes(GetIntegerSize(binr)); + rsaParameters.Q = binr.ReadBytes(GetIntegerSize(binr)); + rsaParameters.DP = binr.ReadBytes(GetIntegerSize(binr)); + rsaParameters.DQ = binr.ReadBytes(GetIntegerSize(binr)); + rsaParameters.InverseQ = binr.ReadBytes(GetIntegerSize(binr)); + } + + rsa.ImportParameters(rsaParameters); + return rsa; + } + + #endregion + + #region 使用公钥创建RSA实例 + /// + /// 使用公钥创建RSA实例 + /// + /// + /// + public RSA? CreateRsaProviderFromPublicKey(string publicKeyString) + { + // encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1" + byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 }; + byte[] seq = new byte[15]; + + var x509Key = Convert.FromBase64String(publicKeyString); + + // --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------ + using (MemoryStream mem = new MemoryStream(x509Key)) + { + using (BinaryReader binr = new BinaryReader(mem)) //wrap Memory Stream with BinaryReader for easy reading + { + byte bt = 0; + ushort twobytes = 0; + + twobytes = binr.ReadUInt16(); + if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81) + binr.ReadByte(); //advance 1 byte + else if (twobytes == 0x8230) + binr.ReadInt16(); //advance 2 bytes + else + return null; + + seq = binr.ReadBytes(15); //read the Sequence OID + if (!CompareBytearrays(seq, seqOid)) //make sure Sequence for OID is correct + return null; + + twobytes = binr.ReadUInt16(); + if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81) + binr.ReadByte(); //advance 1 byte + else if (twobytes == 0x8203) + binr.ReadInt16(); //advance 2 bytes + else + return null; + + bt = binr.ReadByte(); + if (bt != 0x00) //expect null byte next + return null; + + twobytes = binr.ReadUInt16(); + if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81) + binr.ReadByte(); //advance 1 byte + else if (twobytes == 0x8230) + binr.ReadInt16(); //advance 2 bytes + else + return null; + + twobytes = binr.ReadUInt16(); + byte lowbyte = 0x00; + byte highbyte = 0x00; + + if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81) + lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus + else if (twobytes == 0x8202) + { + highbyte = binr.ReadByte(); //advance 2 bytes + lowbyte = binr.ReadByte(); + } + else + return null; + byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order + int modsize = BitConverter.ToInt32(modint, 0); + + int firstbyte = binr.PeekChar(); + if (firstbyte == 0x00) + { //if first byte (highest order) of modulus is zero, don't include it + binr.ReadByte(); //skip this null byte + modsize -= 1; //reduce modulus buffer size by 1 + } + + byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes + + if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data + return null; + int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values) + byte[] exponent = binr.ReadBytes(expbytes); + + // ------- create RSACryptoServiceProvider instance and initialize with public key ----- + var rsa = RSA.Create(); + RSAParameters rsaKeyInfo = new RSAParameters + { + Modulus = modulus, + Exponent = exponent + }; + rsa.ImportParameters(rsaKeyInfo); + + return rsa; + } + + } + } + + #endregion + + #region 导入密钥算法 + + private int GetIntegerSize(BinaryReader binr) + { + byte bt = 0; + int count = 0; + bt = binr.ReadByte(); + if (bt != 0x02) + return 0; + bt = binr.ReadByte(); + + if (bt == 0x81) + count = binr.ReadByte(); + else + if (bt == 0x82) + { + var highbyte = binr.ReadByte(); + var lowbyte = binr.ReadByte(); + byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; + count = BitConverter.ToInt32(modint, 0); + } + else + { + count = bt; + } + + while (binr.ReadByte() == 0x00) + { + count -= 1; + } + binr.BaseStream.Seek(-1, SeekOrigin.Current); + return count; + } + + private bool CompareBytearrays(byte[] a, byte[] b) + { + if (a.Length != b.Length) + return false; + int i = 0; + foreach (byte c in a) + { + if (c != b[i]) + return false; + i++; + } + return true; + } + + #endregion + + } + + /// + /// RSA算法类型 + /// + public enum RSAType + { + /// + /// SHA1 + /// + RSA = 0, + /// + /// RSA2 密钥长度至少为2048 + /// SHA256 + /// + RSA2 + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/RandomHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/RandomHelper.cs new file mode 100644 index 00000000..2a5ba81f --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/RandomHelper.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +namespace Yi.Framework.Core.Helper +{ + public class RandomHelper + { + public static string replaceBianLiang(string content) + { + content = content.Replace("{当前时间}", DateTime.Now.TimeOfDay.ToString()); + string[] bianliang = new string[] { "{随机字母}", "{随机数字}", "{随机汉字}" }; + Regex r; + int count; + string readstr = ""; + foreach (string str in bianliang) + { + count = (content.Length - content.Replace(str, "").Length) / str.Length; + if (str == "{随机汉字}") readstr = RandChina(count); + if (str == "{随机数字}") readstr = GenerateCheckCodeNum(count); + if (str == "{随机字母}") readstr = GenerateRandomLetter(count); + if (count > readstr.Length) count = readstr.Length; + r = new Regex(str.Replace("{", "\\{").Replace("}", "\\}")); + for (int i = 0; i < count; i++) + { + content = r.Replace(content, readstr.Substring(i, 1), 1); + } + } + return content; + } + + + /// + /// 随机生成字母 + /// + /// + /// + public static string GenerateRandomLetter(int Length) + { + char[] Pattern = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + string result = ""; + int n = Pattern.Length; + Random random = new Random(~unchecked((int)DateTime.Now.Ticks)); + for (int i = 0; i < Length; i++) + { + int rnd = random.Next(0, n); + result += Pattern[rnd]; + } + return result; + } + + /// + /// 随机生成数字 + /// + /// + /// + public static string GenerateCheckCodeNum(int codeCount) + { + int rep = 0; + string str = string.Empty; + long num2 = DateTime.Now.Ticks + rep; + rep++; + Random random = new Random(((int)(((ulong)num2) & 0xffffffffL)) | ((int)(num2 >> rep))); + for (int i = 0; i < codeCount; i++) + { + int num = random.Next(); + str = str + ((char)(0x30 + ((ushort)(num % 10)))).ToString(); + } + return str; + } + + /// + /// 此函数为生成指定数目的汉字 + /// + /// 汉字数目 + /// 所有汉字 + public static string RandChina(int charLen) + { + int area, code;//汉字由区位和码位组成(都为0-94,其中区位16-55为一级汉字区,56-87为二级汉字区,1-9为特殊字符区) + StringBuilder strtem = new StringBuilder(); + Random rand = new Random(); + for (int i = 0; i < charLen; i++) + { + area = rand.Next(16, 88); + if (area == 55)//第55区只有89个字符 + { + code = rand.Next(1, 90); + } + else + { + code = rand.Next(1, 94); + } + strtem.Append(Encoding.GetEncoding("GB2312").GetString(new byte[] { Convert.ToByte(area + 160), Convert.ToByte(code + 160) })); + } + return strtem.ToString(); + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/SnowflakeHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/SnowflakeHelper.cs new file mode 100644 index 00000000..95d892ea --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/SnowflakeHelper.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Helper +{ + public static class SnowflakeHelper + { + public static long Next() + { + SnowflakeTool snowflakeTool = new SnowflakeTool(1); + return snowflakeTool.NextId(); + } + + private class SnowflakeTool + { + //机器ID + private static long nodeId; + private static long twepoch = 687888001020L; //唯一时间,这是一个避免重复的随机量,自行设定不要大于当前时间戳 + private static long sequence = 0L; + private static int workerIdBits = 4; //机器码字节数。4个字节用来保存机器码(定义为Long类型会出现,最大偏移64位,所以左移64位没有意义) + public static long maxWorkerId = -1L ^ -1L << workerIdBits; //最大机器ID + private static int sequenceBits = 10; //计数器字节数,10个字节用来保存计数码 + private static int workerIdShift = sequenceBits; //机器码数据左移位数,就是后面计数器占用的位数 + private static int timestampLeftShift = sequenceBits + workerIdBits; //时间戳左移动位数就是机器码和计数器总字节数 + public static long sequenceMask = -1L ^ -1L << sequenceBits; //一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成 + private long lastTimestamp = -1L; + + /// + /// 机器码 + /// + /// + public SnowflakeTool(long workerId) + { + if (workerId > maxWorkerId || workerId < 0) + throw new Exception(string.Format("节点id 不能大于 {0} 或者 小于 0 ", workerId)); + SnowflakeTool.nodeId = workerId; + + } + + public long NextId() + { + lock (this) + { + long timestamp = TimeGen(); + if (this.lastTimestamp == timestamp) + { //同一微妙中生成ID + SnowflakeTool.sequence = (SnowflakeTool.sequence + 1) & SnowflakeTool.sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限 + if (SnowflakeTool.sequence == 0) + { + //一微妙内产生的ID计数已达上限,等待下一微妙 + timestamp = TillNextMillis(this.lastTimestamp); + } + } + else + { //不同微秒生成ID + SnowflakeTool.sequence = 0; //计数清0 + } + if (timestamp < lastTimestamp) + { //如果当前时间戳比上一次生成ID时时间戳还小,抛出异常,因为不能保证现在生成的ID之前没有生成过 + throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds", + this.lastTimestamp - timestamp)); + } + this.lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳 + long nextId = (timestamp - twepoch << timestampLeftShift) | SnowflakeTool.nodeId << SnowflakeTool.workerIdShift | SnowflakeTool.sequence; + return nextId; + } + } + + /// + /// 获取下一微秒时间戳 + /// + /// + /// + private long TillNextMillis(long lastTimestamp) + { + long timestamp = TimeGen(); + while (timestamp <= lastTimestamp) + { + timestamp = TimeGen(); + } + return timestamp; + } + + /// + /// 生成当前时间戳 + /// + /// + private long TimeGen() + { + return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds; + } + } + } + + +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/StringHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/StringHelper.cs new file mode 100644 index 00000000..faa28a5f --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/StringHelper.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Yi.Framework.Core.Helper +{ + public class StringHelper + { + /// + /// 根据分隔符返回前n条数据 + /// + /// 数据内容 + /// 分隔符 + /// 前n条 + /// 是否倒序(默认false) + /// + public static List GetTopDataBySeparator(string content, string separator, int top, bool isDesc = false) + { + if (string.IsNullOrEmpty(content)) + { + return new List() { }; + } + + if (string.IsNullOrEmpty(separator)) + { + throw new ArgumentException("message", nameof(separator)); + } + + var dataArray = content.Split(separator).Where(d => !string.IsNullOrEmpty(d)).ToArray(); + if (isDesc) + { + Array.Reverse(dataArray); + } + + if (top > 0) + { + dataArray = dataArray.Take(top).ToArray(); + } + + return dataArray.ToList(); + } + /// + /// 根据字段拼接get参数 + /// + /// + /// + public static string GetPars(Dictionary dic) + { + + StringBuilder sb = new StringBuilder(); + string? urlPars = null; + bool isEnter = false; + foreach (var item in dic) + { + sb.Append($"{(isEnter ? "&" : "")}{item.Key}={item.Value}"); + isEnter = true; + } + urlPars = sb.ToString(); + return urlPars; + } + /// + /// 根据字段拼接get参数 + /// + /// + /// + public static string GetPars(Dictionary dic) + { + + StringBuilder sb = new StringBuilder(); + string? urlPars = null; + bool isEnter = false; + foreach (var item in dic) + { + sb.Append($"{(isEnter ? "&" : "")}{item.Key}={item.Value}"); + isEnter = true; + } + urlPars = sb.ToString(); + return urlPars; + } + /// + /// 获取一个GUID + /// + /// 格式-默认为N + /// + public static string GetGUID(string format="N") { + return Guid.NewGuid().ToString(format); + } + /// + /// 根据GUID获取19位的唯一数字序列 + /// + /// + public static long GetGuidToLongID() + { + byte[] buffer = Guid.NewGuid().ToByteArray(); + return BitConverter.ToInt64(buffer, 0); + } + /// + /// 获取字符串最后X行 + /// + /// + /// + /// + public static string GetCusLine(string resourceStr, int length) { + string[] arrStr = resourceStr.Split("\r\n"); + return string.Join("", (from q in arrStr select q).Skip(arrStr.Length - length + 1).Take(length).ToArray()); + } + + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/TreeHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/TreeHelper.cs new file mode 100644 index 00000000..bd688170 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/TreeHelper.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Helper +{ + public static class TreeHelper + { + public static List SetTree(List list, Action action = null!) + { + if (list is not null && list.Count > 0) + { + IList result = new List(); + long pid = list.Min(m => (m as ITreeModel)!.ParentId); + IList t = list.Where(m => (m as ITreeModel)!.ParentId == pid).ToList(); + foreach (T model in t) + { + if (action is not null) + { + action(model); + } + result.Add(model); + var item = (model as ITreeModel); + IList children = list.Where(m => (m as ITreeModel)!.ParentId == item!.Id).ToList(); + if (children.Count > 0) + { + SetTreeChildren(list, children, model, action!); + } + } + return result.OrderByDescending(m => (m as ITreeModel)!.OrderNum).ToList(); + } + return null!; + } + private static void SetTreeChildren(IList list, IList children, T model, Action action = null!) + { + var mm = (model as ITreeModel); + mm!.Children = new List(); + foreach (T item in children) + { + if (action is not null) + { + action(item); + } + mm.Children.Add(item); + var _item = (item as ITreeModel); + IList _children = list.Where(m => (m as ITreeModel)!.ParentId == _item!.Id).ToList(); + if (_children.Count > 0) + { + SetTreeChildren(list, _children, item, action!); + } + } + mm.Children = mm.Children.OrderByDescending(m => (m as ITreeModel)!.OrderNum).ToList(); + } + + + public interface ITreeModel + { + public long Id { get; set; } + public long ParentId { get; set; } + public int OrderNum { get; set; } + + public List? Children { get; set; } + } + } + +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/UnicodeHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/UnicodeHelper.cs new file mode 100644 index 00000000..0d8e737f --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/UnicodeHelper.cs @@ -0,0 +1,47 @@ +using System; +using System.Text; +using System.Text.RegularExpressions; + +namespace Yi.Framework.Core.Helper +{ + public static class UnicodeHelper + { + /// + /// 字符串转Unicode码 + /// + /// The to unicode. + /// Value. + public static string StringToUnicode(string value) + { + byte[] bytes = Encoding.Unicode.GetBytes(value); + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < bytes.Length; i += 2) + { + // 取两个字符,每个字符都是右对齐。 + stringBuilder.AppendFormat("u{0}{1}", bytes[i + 1].ToString("x").PadLeft(2, '0'), bytes[i].ToString("x").PadLeft(2, '0')); + } + return stringBuilder.ToString(); + } + + /// + /// Unicode转字符串 + /// + /// The to string. + /// Unicode. + public static string UnicodeToString(string unicode) + { + unicode = unicode.Replace("%", "\\"); + + return new Regex(@"\\u([0-9A-F]{4})", RegexOptions.IgnoreCase | RegexOptions.Compiled).Replace( + unicode, x => string.Empty + Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16))); + + //string resultStr = ""; + //string[] strList = unicode.Split('u'); + //for (int i = 1; i < strList.Length; i++) + //{ + // resultStr += (char)int.Parse(strList[i], System.Globalization.NumberStyles.HexNumber); + //} + //return resultStr; + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/UrlHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/UrlHelper.cs new file mode 100644 index 00000000..ed073407 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/UrlHelper.cs @@ -0,0 +1,23 @@ +namespace Yi.Framework.Core.Helper +{ + public class UrlHelper + { + /// + /// UrlEncode编码 + /// + /// url + /// + public static string UrlEncode(string url) { + return System.Web.HttpUtility.UrlEncode(url, System.Text.Encoding.UTF8); + } + /// + /// UrlEncode解码 + /// + /// 数据 + /// + public static string UrlDecode(string data) + { + return System.Web.HttpUtility.UrlDecode(data, System.Text.Encoding.UTF8); + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Helper/XmlHelper.cs b/src/Yi.Framework/Yi.Framework.Core/Helper/XmlHelper.cs new file mode 100644 index 00000000..f40dd811 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Helper/XmlHelper.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml.Serialization; + +namespace Yi.Framework.Core.Helper +{ + public class XmlHelper + { + /// + /// 转换对象为JSON格式数据 + /// + /// + /// 对象 + /// 字符格式的JSON数据 + public static string? GetXML(object obj) + { + try + { + XmlSerializer xs = new XmlSerializer(typeof(T)); + + using (TextWriter tw = new StringWriter()) + { + xs.Serialize(tw, obj); + return tw.ToString(); + } + } + catch (Exception) + { + return string.Empty; + } + } + + /// + /// Xml格式字符转换为T类型的对象 + /// + /// + /// + /// + public static T ParseFormByXml(string xml,string rootName="root") + { + XmlSerializer serializer = new XmlSerializer(typeof(T), new XmlRootAttribute(rootName)); + StringReader reader = new StringReader(xml); + + T res = (T)serializer.Deserialize(reader)!; + reader.Close(); + reader.Dispose(); + return res; + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/YiFrameworkCoreModule.cs b/src/Yi.Framework/Yi.Framework.Core/YiFrameworkCoreModule.cs index 8ef8755c..8178b352 100644 --- a/src/Yi.Framework/Yi.Framework.Core/YiFrameworkCoreModule.cs +++ b/src/Yi.Framework/Yi.Framework.Core/YiFrameworkCoreModule.cs @@ -19,13 +19,18 @@ namespace Yi.Framework.Core { //服务定位实例赋值 ServiceLocatorModel.Instance = app.ApplicationServices; + + //全局错误,需要靠前 + app.UseErrorHandlingServer(); } public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) { + //添加全局配置类 services.AddSingleton(new Appsettings(context.Configuration)); - + //全盘扫描,自动依赖注入 + services.AddAutoIocServer(); //全局日志 GobalLogModel.SqlLogEnable = Appsettings.appBool("SqlLog_Enable"); diff --git a/src/Yi.Framework/Yi.Framework.Ddd.Application/Dtos/EntityDto.cs b/src/Yi.Framework/Yi.Framework.Ddd.Application/Dtos/EntityDto.cs new file mode 100644 index 00000000..a0dc20c6 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Ddd.Application/Dtos/EntityDto.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Ddd.Dtos +{ + [Serializable] + public abstract class EntityDto : EntityDto, IEntityDto, IEntityDto + { + // + // 摘要: + // Id of the entity. + public TKey Id { get; set; } + + public override string ToString() + { + return $"[DTO: {GetType().Name}] Id = {Id}"; + } + } + + [Serializable] + public abstract class EntityDto : IEntityDto + { + public override string ToString() + { + return "[DTO: " + GetType().Name + "]"; + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Ddd.Application/Dtos/IEntityDto.cs b/src/Yi.Framework/Yi.Framework.Ddd.Application/Dtos/IEntityDto.cs new file mode 100644 index 00000000..5aeed368 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Ddd.Application/Dtos/IEntityDto.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Ddd.Dtos +{ + public interface IEntityDto + { + } + + public interface IEntityDto : IEntityDto + { + TKey Id { get; set; } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Ddd.Application/Entities/Entity.cs b/src/Yi.Framework/Yi.Framework.Ddd.Application/Entities/Entity.cs new file mode 100644 index 00000000..0b1b695c --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Ddd.Application/Entities/Entity.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Ddd.Entities +{ + [Serializable] + public abstract class Entity : IEntity + { + protected Entity() + { + } + + public override string ToString() + { + return "[ENTITY: " + GetType().Name + "] Keys = " + GetKeys(); + } + + public abstract object[] GetKeys(); + + } + + [Serializable] + public abstract class Entity : Entity, IEntity, IEntity + { + public virtual TKey Id { get; protected set; } + + protected Entity() + { + } + + protected Entity(TKey id) + { + Id = id; + } + + public override object[] GetKeys() + { + return new object[1] { Id }; + } + + public override string ToString() + { + return $"[ENTITY: {GetType().Name}] Id = {Id}"; + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Ddd.Application/Entities/IEntity.cs b/src/Yi.Framework/Yi.Framework.Ddd.Application/Entities/IEntity.cs new file mode 100644 index 00000000..73c9168e --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Ddd.Application/Entities/IEntity.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Ddd.Entities +{ + public interface IEntity + { + // + // 摘要: + // Returns an array of ordered keys for this entity. + object[] GetKeys(); + } + public interface IEntity : IEntity + { + // + // 摘要: + // Unique identifier for this entity. + TKey Id { get; } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Ddd.Application/Services/ApplicationService.cs b/src/Yi.Framework/Yi.Framework.Ddd.Application/Services/ApplicationService.cs new file mode 100644 index 00000000..bda9830b --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Ddd.Application/Services/ApplicationService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Ddd.Services +{ + public abstract class ApplicationService + { + } +} diff --git a/src/Yi.Framework/Yi.Framework.Ddd.Application/Services/IApplicationService.cs b/src/Yi.Framework/Yi.Framework.Ddd.Application/Services/IApplicationService.cs new file mode 100644 index 00000000..c5491cb2 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Ddd.Application/Services/IApplicationService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Ddd.Services +{ + public interface IApplicationService + { + } +} diff --git a/src/Yi.Framework/Yi.Framework.Ddd.Application/Yi.Framework.Ddd.csproj b/src/Yi.Framework/Yi.Framework.Ddd.Application/Yi.Framework.Ddd.csproj index f9a08c82..e7101d08 100644 --- a/src/Yi.Framework/Yi.Framework.Ddd.Application/Yi.Framework.Ddd.csproj +++ b/src/Yi.Framework/Yi.Framework.Ddd.Application/Yi.Framework.Ddd.csproj @@ -7,7 +7,6 @@ - diff --git a/src/Yi.Framework/Yi.Framework.Web/TestEntity.cs b/src/Yi.Framework/Yi.Framework.Web/TestEntity.cs index 4a8735b3..242d5933 100644 --- a/src/Yi.Framework/Yi.Framework.Web/TestEntity.cs +++ b/src/Yi.Framework/Yi.Framework.Web/TestEntity.cs @@ -1,6 +1,9 @@ -namespace Yi.Framework.Web +using Yi.Framework.Core.Attribute; +using Yi.Framework.Core.DependencyInjection; + +namespace Yi.Framework.Web { - public class TestEntity + public class TestEntity: ITransientDependency { } } diff --git a/src/Yi.Framework/Yi.Framework.Web/Yi.Framework.Web.csproj b/src/Yi.Framework/Yi.Framework.Web/Yi.Framework.Web.csproj index f9cd981f..db54d323 100644 --- a/src/Yi.Framework/Yi.Framework.Web/Yi.Framework.Web.csproj +++ b/src/Yi.Framework/Yi.Framework.Web/Yi.Framework.Web.csproj @@ -8,6 +8,7 @@ + diff --git a/src/Yi.Framework/Yi.Framework.sln b/src/Yi.Framework/Yi.Framework.sln index 350aff8c..251d1ebc 100644 --- a/src/Yi.Framework/Yi.Framework.sln +++ b/src/Yi.Framework/Yi.Framework.sln @@ -31,8 +31,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Core.Autofac", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AspNetCore", "Yi.Framework.AspNetCore\Yi.Framework.AspNetCore.csproj", "{2F5E5843-14FB-48F1-AEB0-B9FFE103B972}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.BackgroundJobs", "Yi.Framework.BackgroundJobs\Yi.Framework.BackgroundJobs.csproj", "{E569E5AA-3CC1-459A-B5DD-5D340B551A44}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Caching", "Yi.Framework.Caching\Yi.Framework.Caching.csproj", "{8767C5B7-3A17-4729-BCAA-B391B6A215AA}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Caching.Redis", "Yi.Framework.Caching.Redis\Yi.Framework.Caching.Redis.csproj", "{F13D4F03-3FA0-43E9-BBAA-F618E1A3CF41}" @@ -43,7 +41,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Uow", "Yi.Fram EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Core.Sqlsugar", "Yi.Framework.Core.Sqlsugar\Yi.Framework.Core.Sqlsugar.csproj", "{58F4071D-66B7-4839-A247-79AF0E4E1C8E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Core.AutoMapper", "Yi.Framework.Core.AutoMapper\Yi.Framework.Core.AutoMapper.csproj", "{DFD34702-2EF6-4ECC-AE6E-9A1A3885BD26}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Core.AutoMapper", "Yi.Framework.Core.AutoMapper\Yi.Framework.Core.AutoMapper.csproj", "{DFD34702-2EF6-4ECC-AE6E-9A1A3885BD26}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -95,10 +93,6 @@ Global {2F5E5843-14FB-48F1-AEB0-B9FFE103B972}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F5E5843-14FB-48F1-AEB0-B9FFE103B972}.Release|Any CPU.ActiveCfg = Release|Any CPU {2F5E5843-14FB-48F1-AEB0-B9FFE103B972}.Release|Any CPU.Build.0 = Release|Any CPU - {E569E5AA-3CC1-459A-B5DD-5D340B551A44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E569E5AA-3CC1-459A-B5DD-5D340B551A44}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E569E5AA-3CC1-459A-B5DD-5D340B551A44}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E569E5AA-3CC1-459A-B5DD-5D340B551A44}.Release|Any CPU.Build.0 = Release|Any CPU {8767C5B7-3A17-4729-BCAA-B391B6A215AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8767C5B7-3A17-4729-BCAA-B391B6A215AA}.Debug|Any CPU.Build.0 = Debug|Any CPU {8767C5B7-3A17-4729-BCAA-B391B6A215AA}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -139,7 +133,6 @@ Global {949F35A7-36E4-4080-9940-24BE52532078} = {5F2B846D-96CE-400A-878E-220498F4EE31} {63BA134E-9D23-4EB8-87E4-B45B33D954F5} = {5F2B846D-96CE-400A-878E-220498F4EE31} {2F5E5843-14FB-48F1-AEB0-B9FFE103B972} = {5F2B846D-96CE-400A-878E-220498F4EE31} - {E569E5AA-3CC1-459A-B5DD-5D340B551A44} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806} {8767C5B7-3A17-4729-BCAA-B391B6A215AA} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806} {F13D4F03-3FA0-43E9-BBAA-F618E1A3CF41} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806} {67CF07AB-2A72-4B36-A3A5-4CEB82B7C43C} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}