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}