diff --git a/Yi.Framework.Net6/Build.props b/Yi.Framework.Net6/Build.props
new file mode 100644
index 00000000..ee47ef8a
--- /dev/null
+++ b/Yi.Framework.Net6/Build.props
@@ -0,0 +1,3 @@
+
+
+
diff --git a/Yi.Framework.Net6/Version.cs b/Yi.Framework.Net6/Version.cs
new file mode 100644
index 00000000..f5b81f50
--- /dev/null
+++ b/Yi.Framework.Net6/Version.cs
@@ -0,0 +1,90 @@
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyCompany("YiFramework")]
+[assembly: AssemblyFileVersion(VersionInfo.FullVersion)]
+[assembly: AssemblyInformationalVersion(VersionInfo.FullVersion)]
+[assembly: AssemblyVersion(VersionInfo.FullVersion)]
+[assembly: ComVisible(false)]
+
+#pragma warning disable IDE1006 // 命名样式
+internal static class VersionInfo
+{
+ ///
+ /// 主版本: 项目进行了重大修改,导致不再向下兼容,主版本号加1,其它版本号清0;
+ ///
+ public const string Major = "1";
+
+ ///
+ /// 次版本:项目进行了重构,增加了功能,但向下兼容,子版本号加1,主版本号不变, 修正版本号清0;
+ ///
+ public const string Minor = "1";
+
+ ///
+ /// 生成号
+ ///
+ public const string Build = "0";
+
+ ///
+ /// 修订号:项目进行了Bug修复,向下兼容,修正版本号加1,主版本号、子版本号不 变;
+ ///
+ public const string Revision = "0";
+
+ ///
+ /// 版本名称
+ ///
+ public const string VersionName = null;
+
+ ///
+ /// 版本
+ ///
+ public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
+#pragma warning disable CS1570 // XML 注释出现 XML 格式错误
+ ///
+ /// 比较 a,b两个版本
+ /// 当 a > b 时,返回 1
+ /// 当 a = b 时,返回 0
+ /// 当 a < b 时,返回 -1
+ ///
+#pragma warning restore CS1570 // XML 注释出现 XML 格式错误
+ public static int Compare(this Version a, Version b)
+
+ {
+ // 比较主版本
+ if (a.Major != b.Major)
+ {
+ return a.Major > b.Major ? 1 : -1;
+ }
+
+ // 比较次版本
+ if (a.Minor != b.Minor)
+ {
+ return a.Minor > b.Minor ? 1 : -1;
+ }
+
+ // 比较生成号
+ if (a.Build < 0 || b.Build < 0)
+ {
+ return 0;
+ }
+
+ if (a.Build != b.Build)
+ {
+ return a.Build > b.Build ? 1 : -1;
+ }
+
+ // 比较修订号
+ if (a.Revision < 0 || b.Revision < 0)
+ {
+ return 0;
+ }
+ if (a.Revision != b.Revision)
+ {
+ return a.Revision > b.Revision ? 1 : -1;
+ }
+
+ return 0;
+ }
+#pragma warning restore IDE1006 // 命名样式
+}
\ No newline at end of file
diff --git a/Yi.Framework.Net6/Yi.Framework.sln b/Yi.Framework.Net6/Yi.Framework.sln
new file mode 100644
index 00000000..c47f2103
--- /dev/null
+++ b/Yi.Framework.Net6/Yi.Framework.sln
@@ -0,0 +1,332 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33103.184
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{EEF5F221-0E32-4A3D-B647-B4B5E7305806}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{32A813F5-13B2-4DCA-8B59-F27F1B0D5678}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "framework", "framework", "{5F2B846D-96CE-400A-878E-220498F4EE31}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Core", "src\framework\Yi.Framework.Core\Yi.Framework.Core.csproj", "{83B2D7AD-ED8E-4392-B0AE-4227498CD75F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Template.Application", "src\project\template\Yi.Template.Application\Yi.Template.Application.csproj", "{456835D1-4968-4195-9993-B2A580E85056}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Template.Application.Contracts", "src\project\template\Yi.Template.Application.Contracts\Yi.Template.Application.Contracts.csproj", "{D2378C23-2CFE-468A-924A-B8C9D4A3A8ED}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Template.Domain", "src\project\template\Yi.Template.Domain\Yi.Template.Domain.csproj", "{C02A954D-CCCB-41BD-ADAD-9D7ECBF1A828}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Template.Domain.Shared", "src\project\template\Yi.Template.Domain.Shared\Yi.Template.Domain.Shared.csproj", "{26171153-1784-455B-9582-0558AEEC03CF}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Template.Sqlsugar", "src\project\template\Yi.Template.Sqlsugar\Yi.Template.Sqlsugar.csproj", "{3C3A7BAC-F27F-433E-BF91-289FA42E4995}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Template.Web", "src\project\template\Yi.Template.Web\Yi.Template.Web.csproj", "{01CC7B62-F42C-45CE-BACA-F450593A1AF2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.BackgroundJobs.Quartz", "src\module\Yi.Framework.BackgroundJobs.Quartz\Yi.Framework.BackgroundJobs.Quartz.csproj", "{1879A863-9864-4E16-8492-504055807684}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Ddd", "src\framework\Yi.Framework.Ddd\Yi.Framework.Ddd.csproj", "{949F35A7-36E4-4080-9940-24BE52532078}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Core.Autofac", "src\framework\Yi.Framework.Core.Autofac\Yi.Framework.Core.Autofac.csproj", "{63BA134E-9D23-4EB8-87E4-B45B33D954F5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AspNetCore", "src\framework\Yi.Framework.AspNetCore\Yi.Framework.AspNetCore.csproj", "{2F5E5843-14FB-48F1-AEB0-B9FFE103B972}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Caching", "src\module\Yi.Framework.Caching\Yi.Framework.Caching.csproj", "{8767C5B7-3A17-4729-BCAA-B391B6A215AA}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Caching.Redis", "src\module\Yi.Framework.Caching.Redis\Yi.Framework.Caching.Redis.csproj", "{F13D4F03-3FA0-43E9-BBAA-F618E1A3CF41}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Caching.MemoryCache", "src\module\Yi.Framework.Caching.MemoryCache\Yi.Framework.Caching.MemoryCache.csproj", "{67CF07AB-2A72-4B36-A3A5-4CEB82B7C43C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Uow", "src\framework\Yi.Framework.Uow\Yi.Framework.Uow.csproj", "{3D83BE69-71BB-43BE-B3F1-A532215561CD}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Core.Sqlsugar", "src\framework\Yi.Framework.Core.Sqlsugar\Yi.Framework.Core.Sqlsugar.csproj", "{58F4071D-66B7-4839-A247-79AF0E4E1C8E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Core.Mapster", "src\framework\Yi.Framework.Core.AutoMapper\Yi.Framework.Core.Mapster.csproj", "{DFD34702-2EF6-4ECC-AE6E-9A1A3885BD26}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Office.Excel", "src\module\Yi.Framework.Office.Excel\Yi.Framework.Office.Excel.csproj", "{4EEC6607-F0D8-4277-9463-104DA7E184B6}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.WeChatPay", "src\module\Yi.Framework.WeChatPay\Yi.Framework.WeChatPay.csproj", "{588D0DA9-303A-4FF0-A2D1-83037E2B269F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Data", "src\framework\Yi.Framework.Data\Yi.Framework.Data.csproj", "{DEE07142-32CE-4B5F-A5A3-452064EBF4A2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Auth.JwtBearer", "src\framework\Yi.Framework.Auth.JwtBearer\Yi.Framework.Auth.JwtBearer.csproj", "{D40C583D-58BE-422D-9A57-94DECB751EB4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Template", "src\module\Yi.Framework.Template\Yi.Framework.Template.csproj", "{134C4AB9-2AFE-4383-84DE-825DF9499CB4}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "template", "template", "{A3707874-7890-42AF-A686-E3AACD6F108C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bbs", "bbs", "{B758A87D-0BFA-44A5-BA33-FBA44151CEB4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.BBS.Domain.Shared", "src\project\bbs\Yi.BBS.Domain.Shared\Yi.BBS.Domain.Shared.csproj", "{DEA3342F-1954-4EE9-9A59-CAF1D7832F33}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.BBS.Domain", "src\project\bbs\Yi.BBS.Domain\Yi.BBS.Domain.csproj", "{86C82BB6-E333-40E8-8DDE-20C3A538433C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.BBS.Application.Contracts", "src\project\bbs\Yi.BBS.Application.Contracts\Yi.BBS.Application.Contracts.csproj", "{679625DD-4BF6-4CD6-99FD-7A3E6D9B04A1}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.BBS.Sqlsugar", "src\project\bbs\Yi.BBS.Sqlsugar\Yi.BBS.Sqlsugar.csproj", "{A8043204-9DAC-4F08-8C73-423CB72927EF}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.BBS.Web", "src\project\bbs\Yi.BBS.Web\Yi.BBS.Web.csproj", "{83BE964D-D53C-4D1B-B8C6-5306C393C07F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.BBS.Application", "src\project\bbs\Yi.BBS.Application\Yi.BBS.Application.csproj", "{959A33C5-7826-4AE7-AC51-40BDC2B767B2}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rbac", "rbac", "{07C9E949-DB5E-4315-A497-FF73746667D8}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.RBAC.Domain.Shared", "src\project\rbac\Yi.RBAC.Domain.Shared\Yi.RBAC.Domain.Shared.csproj", "{5467178B-3731-4346-A0A3-3CB1AC0953AB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.RBAC.Domain", "src\project\rbac\Yi.RBAC.Domain\Yi.RBAC.Domain.csproj", "{2E082104-D3A6-40DE-A4E5-DE326B75A62D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.RBAC.Sqlsugar", "src\project\rbac\Yi.RBAC.Sqlsugar\Yi.RBAC.Sqlsugar.csproj", "{ECF1AA6F-8FCD-428F-9648-2DAE3C345C96}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.RBAC.Application.Contracts", "src\project\rbac\Yi.RBAC.Application.Contracts\Yi.RBAC.Application.Contracts.csproj", "{478DA36E-F547-49CD-8B48-41DC5551C5C2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.RBAC.Application", "src\project\rbac\Yi.RBAC.Application\Yi.RBAC.Application.csproj", "{2074EA00-59A4-49CE-97A6-735F4B77443B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.RBAC.Web", "src\project\rbac\Yi.RBAC.Web\Yi.RBAC.Web.csproj", "{0C031C7D-6F80-4559-977C-AC001036EC44}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ImageSharp", "src\module\Yi.Framework.ImageSharp\Yi.Framework.ImageSharp.csproj", "{60E54034-792C-4A90-BCDF-4D5FFB45089E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.EventBus", "src\module\Yi.Framework.EventBus\Yi.Framework.EventBus.csproj", "{FC559052-36EC-4379-B447-298FAD6045F4}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{12EA3BCF-8991-4010-B41E-67C476CBA690}"
+ ProjectSection(SolutionItems) = preProject
+ ..\.gitignore = ..\.gitignore
+ Build.props = Build.props
+ ..\readme\git提交规范.txt = ..\readme\git提交规范.txt
+ src\project\rbac\GlobalUsings.cs = src\project\rbac\GlobalUsings.cs
+ Version.cs = Version.cs
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.OperLogManager", "src\module\Yi.Framework.OperLogManager\Yi.Framework.OperLogManager.csproj", "{8A604A6B-D1FA-4CFF-BCF5-557519B10FCB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.FileManager", "src\module\Yi.Framework.FileManager\Yi.Framework.FileManager.csproj", "{1BF3115D-B027-4805-AF7B-41B3AE9CB355}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.MultiTenancy", "src\framework\Yi.Framework.MultiTenancy\Yi.Framework.MultiTenancy.csproj", "{590B1EC0-CDA9-4937-BE07-FBB04437D21F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.DictionaryManager", "src\module\Yi.Framework.DictionaryManager\Yi.Framework.DictionaryManager.csproj", "{8941B30D-698B-477A-8737-43E7B4A8695A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Sms.Aliyun", "src\module\Yi.Framework.Sms.Aliyun\Yi.Framework.Sms.Aliyun.csproj", "{063178CF-C5B9-463C-A8A4-F32B743818E2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {83B2D7AD-ED8E-4392-B0AE-4227498CD75F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {83B2D7AD-ED8E-4392-B0AE-4227498CD75F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {83B2D7AD-ED8E-4392-B0AE-4227498CD75F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {83B2D7AD-ED8E-4392-B0AE-4227498CD75F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {456835D1-4968-4195-9993-B2A580E85056}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {456835D1-4968-4195-9993-B2A580E85056}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {456835D1-4968-4195-9993-B2A580E85056}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {456835D1-4968-4195-9993-B2A580E85056}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D2378C23-2CFE-468A-924A-B8C9D4A3A8ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D2378C23-2CFE-468A-924A-B8C9D4A3A8ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D2378C23-2CFE-468A-924A-B8C9D4A3A8ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D2378C23-2CFE-468A-924A-B8C9D4A3A8ED}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C02A954D-CCCB-41BD-ADAD-9D7ECBF1A828}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C02A954D-CCCB-41BD-ADAD-9D7ECBF1A828}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C02A954D-CCCB-41BD-ADAD-9D7ECBF1A828}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C02A954D-CCCB-41BD-ADAD-9D7ECBF1A828}.Release|Any CPU.Build.0 = Release|Any CPU
+ {26171153-1784-455B-9582-0558AEEC03CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {26171153-1784-455B-9582-0558AEEC03CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {26171153-1784-455B-9582-0558AEEC03CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {26171153-1784-455B-9582-0558AEEC03CF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3C3A7BAC-F27F-433E-BF91-289FA42E4995}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3C3A7BAC-F27F-433E-BF91-289FA42E4995}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3C3A7BAC-F27F-433E-BF91-289FA42E4995}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3C3A7BAC-F27F-433E-BF91-289FA42E4995}.Release|Any CPU.Build.0 = Release|Any CPU
+ {01CC7B62-F42C-45CE-BACA-F450593A1AF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {01CC7B62-F42C-45CE-BACA-F450593A1AF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {01CC7B62-F42C-45CE-BACA-F450593A1AF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {01CC7B62-F42C-45CE-BACA-F450593A1AF2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1879A863-9864-4E16-8492-504055807684}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1879A863-9864-4E16-8492-504055807684}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1879A863-9864-4E16-8492-504055807684}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1879A863-9864-4E16-8492-504055807684}.Release|Any CPU.Build.0 = Release|Any CPU
+ {949F35A7-36E4-4080-9940-24BE52532078}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {949F35A7-36E4-4080-9940-24BE52532078}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {949F35A7-36E4-4080-9940-24BE52532078}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {949F35A7-36E4-4080-9940-24BE52532078}.Release|Any CPU.Build.0 = Release|Any CPU
+ {63BA134E-9D23-4EB8-87E4-B45B33D954F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {63BA134E-9D23-4EB8-87E4-B45B33D954F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {63BA134E-9D23-4EB8-87E4-B45B33D954F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {63BA134E-9D23-4EB8-87E4-B45B33D954F5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2F5E5843-14FB-48F1-AEB0-B9FFE103B972}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {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
+ {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
+ {8767C5B7-3A17-4729-BCAA-B391B6A215AA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F13D4F03-3FA0-43E9-BBAA-F618E1A3CF41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F13D4F03-3FA0-43E9-BBAA-F618E1A3CF41}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F13D4F03-3FA0-43E9-BBAA-F618E1A3CF41}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F13D4F03-3FA0-43E9-BBAA-F618E1A3CF41}.Release|Any CPU.Build.0 = Release|Any CPU
+ {67CF07AB-2A72-4B36-A3A5-4CEB82B7C43C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {67CF07AB-2A72-4B36-A3A5-4CEB82B7C43C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {67CF07AB-2A72-4B36-A3A5-4CEB82B7C43C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {67CF07AB-2A72-4B36-A3A5-4CEB82B7C43C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3D83BE69-71BB-43BE-B3F1-A532215561CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3D83BE69-71BB-43BE-B3F1-A532215561CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3D83BE69-71BB-43BE-B3F1-A532215561CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3D83BE69-71BB-43BE-B3F1-A532215561CD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {58F4071D-66B7-4839-A247-79AF0E4E1C8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {58F4071D-66B7-4839-A247-79AF0E4E1C8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {58F4071D-66B7-4839-A247-79AF0E4E1C8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {58F4071D-66B7-4839-A247-79AF0E4E1C8E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DFD34702-2EF6-4ECC-AE6E-9A1A3885BD26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DFD34702-2EF6-4ECC-AE6E-9A1A3885BD26}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DFD34702-2EF6-4ECC-AE6E-9A1A3885BD26}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DFD34702-2EF6-4ECC-AE6E-9A1A3885BD26}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4EEC6607-F0D8-4277-9463-104DA7E184B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4EEC6607-F0D8-4277-9463-104DA7E184B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4EEC6607-F0D8-4277-9463-104DA7E184B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4EEC6607-F0D8-4277-9463-104DA7E184B6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {588D0DA9-303A-4FF0-A2D1-83037E2B269F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {588D0DA9-303A-4FF0-A2D1-83037E2B269F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {588D0DA9-303A-4FF0-A2D1-83037E2B269F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {588D0DA9-303A-4FF0-A2D1-83037E2B269F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DEE07142-32CE-4B5F-A5A3-452064EBF4A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DEE07142-32CE-4B5F-A5A3-452064EBF4A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DEE07142-32CE-4B5F-A5A3-452064EBF4A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DEE07142-32CE-4B5F-A5A3-452064EBF4A2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D40C583D-58BE-422D-9A57-94DECB751EB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D40C583D-58BE-422D-9A57-94DECB751EB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D40C583D-58BE-422D-9A57-94DECB751EB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D40C583D-58BE-422D-9A57-94DECB751EB4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {134C4AB9-2AFE-4383-84DE-825DF9499CB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {134C4AB9-2AFE-4383-84DE-825DF9499CB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {134C4AB9-2AFE-4383-84DE-825DF9499CB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {134C4AB9-2AFE-4383-84DE-825DF9499CB4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DEA3342F-1954-4EE9-9A59-CAF1D7832F33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DEA3342F-1954-4EE9-9A59-CAF1D7832F33}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DEA3342F-1954-4EE9-9A59-CAF1D7832F33}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DEA3342F-1954-4EE9-9A59-CAF1D7832F33}.Release|Any CPU.Build.0 = Release|Any CPU
+ {86C82BB6-E333-40E8-8DDE-20C3A538433C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {86C82BB6-E333-40E8-8DDE-20C3A538433C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {86C82BB6-E333-40E8-8DDE-20C3A538433C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {86C82BB6-E333-40E8-8DDE-20C3A538433C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {679625DD-4BF6-4CD6-99FD-7A3E6D9B04A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {679625DD-4BF6-4CD6-99FD-7A3E6D9B04A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {679625DD-4BF6-4CD6-99FD-7A3E6D9B04A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {679625DD-4BF6-4CD6-99FD-7A3E6D9B04A1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A8043204-9DAC-4F08-8C73-423CB72927EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A8043204-9DAC-4F08-8C73-423CB72927EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A8043204-9DAC-4F08-8C73-423CB72927EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A8043204-9DAC-4F08-8C73-423CB72927EF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {83BE964D-D53C-4D1B-B8C6-5306C393C07F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {83BE964D-D53C-4D1B-B8C6-5306C393C07F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {83BE964D-D53C-4D1B-B8C6-5306C393C07F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {83BE964D-D53C-4D1B-B8C6-5306C393C07F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {959A33C5-7826-4AE7-AC51-40BDC2B767B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {959A33C5-7826-4AE7-AC51-40BDC2B767B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {959A33C5-7826-4AE7-AC51-40BDC2B767B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {959A33C5-7826-4AE7-AC51-40BDC2B767B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5467178B-3731-4346-A0A3-3CB1AC0953AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5467178B-3731-4346-A0A3-3CB1AC0953AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5467178B-3731-4346-A0A3-3CB1AC0953AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5467178B-3731-4346-A0A3-3CB1AC0953AB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2E082104-D3A6-40DE-A4E5-DE326B75A62D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2E082104-D3A6-40DE-A4E5-DE326B75A62D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2E082104-D3A6-40DE-A4E5-DE326B75A62D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2E082104-D3A6-40DE-A4E5-DE326B75A62D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ECF1AA6F-8FCD-428F-9648-2DAE3C345C96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ECF1AA6F-8FCD-428F-9648-2DAE3C345C96}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ECF1AA6F-8FCD-428F-9648-2DAE3C345C96}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ECF1AA6F-8FCD-428F-9648-2DAE3C345C96}.Release|Any CPU.Build.0 = Release|Any CPU
+ {478DA36E-F547-49CD-8B48-41DC5551C5C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {478DA36E-F547-49CD-8B48-41DC5551C5C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {478DA36E-F547-49CD-8B48-41DC5551C5C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {478DA36E-F547-49CD-8B48-41DC5551C5C2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2074EA00-59A4-49CE-97A6-735F4B77443B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2074EA00-59A4-49CE-97A6-735F4B77443B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2074EA00-59A4-49CE-97A6-735F4B77443B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2074EA00-59A4-49CE-97A6-735F4B77443B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0C031C7D-6F80-4559-977C-AC001036EC44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0C031C7D-6F80-4559-977C-AC001036EC44}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0C031C7D-6F80-4559-977C-AC001036EC44}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0C031C7D-6F80-4559-977C-AC001036EC44}.Release|Any CPU.Build.0 = Release|Any CPU
+ {60E54034-792C-4A90-BCDF-4D5FFB45089E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {60E54034-792C-4A90-BCDF-4D5FFB45089E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {60E54034-792C-4A90-BCDF-4D5FFB45089E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {60E54034-792C-4A90-BCDF-4D5FFB45089E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FC559052-36EC-4379-B447-298FAD6045F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FC559052-36EC-4379-B447-298FAD6045F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FC559052-36EC-4379-B447-298FAD6045F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FC559052-36EC-4379-B447-298FAD6045F4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8A604A6B-D1FA-4CFF-BCF5-557519B10FCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8A604A6B-D1FA-4CFF-BCF5-557519B10FCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8A604A6B-D1FA-4CFF-BCF5-557519B10FCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8A604A6B-D1FA-4CFF-BCF5-557519B10FCB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1BF3115D-B027-4805-AF7B-41B3AE9CB355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1BF3115D-B027-4805-AF7B-41B3AE9CB355}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1BF3115D-B027-4805-AF7B-41B3AE9CB355}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1BF3115D-B027-4805-AF7B-41B3AE9CB355}.Release|Any CPU.Build.0 = Release|Any CPU
+ {590B1EC0-CDA9-4937-BE07-FBB04437D21F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {590B1EC0-CDA9-4937-BE07-FBB04437D21F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {590B1EC0-CDA9-4937-BE07-FBB04437D21F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {590B1EC0-CDA9-4937-BE07-FBB04437D21F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8941B30D-698B-477A-8737-43E7B4A8695A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8941B30D-698B-477A-8737-43E7B4A8695A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8941B30D-698B-477A-8737-43E7B4A8695A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8941B30D-698B-477A-8737-43E7B4A8695A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {063178CF-C5B9-463C-A8A4-F32B743818E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {063178CF-C5B9-463C-A8A4-F32B743818E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {063178CF-C5B9-463C-A8A4-F32B743818E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {063178CF-C5B9-463C-A8A4-F32B743818E2}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {83B2D7AD-ED8E-4392-B0AE-4227498CD75F} = {5F2B846D-96CE-400A-878E-220498F4EE31}
+ {456835D1-4968-4195-9993-B2A580E85056} = {A3707874-7890-42AF-A686-E3AACD6F108C}
+ {D2378C23-2CFE-468A-924A-B8C9D4A3A8ED} = {A3707874-7890-42AF-A686-E3AACD6F108C}
+ {C02A954D-CCCB-41BD-ADAD-9D7ECBF1A828} = {A3707874-7890-42AF-A686-E3AACD6F108C}
+ {26171153-1784-455B-9582-0558AEEC03CF} = {A3707874-7890-42AF-A686-E3AACD6F108C}
+ {3C3A7BAC-F27F-433E-BF91-289FA42E4995} = {A3707874-7890-42AF-A686-E3AACD6F108C}
+ {01CC7B62-F42C-45CE-BACA-F450593A1AF2} = {A3707874-7890-42AF-A686-E3AACD6F108C}
+ {1879A863-9864-4E16-8492-504055807684} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}
+ {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}
+ {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}
+ {3D83BE69-71BB-43BE-B3F1-A532215561CD} = {5F2B846D-96CE-400A-878E-220498F4EE31}
+ {58F4071D-66B7-4839-A247-79AF0E4E1C8E} = {5F2B846D-96CE-400A-878E-220498F4EE31}
+ {DFD34702-2EF6-4ECC-AE6E-9A1A3885BD26} = {5F2B846D-96CE-400A-878E-220498F4EE31}
+ {4EEC6607-F0D8-4277-9463-104DA7E184B6} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}
+ {588D0DA9-303A-4FF0-A2D1-83037E2B269F} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}
+ {DEE07142-32CE-4B5F-A5A3-452064EBF4A2} = {5F2B846D-96CE-400A-878E-220498F4EE31}
+ {D40C583D-58BE-422D-9A57-94DECB751EB4} = {5F2B846D-96CE-400A-878E-220498F4EE31}
+ {134C4AB9-2AFE-4383-84DE-825DF9499CB4} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}
+ {A3707874-7890-42AF-A686-E3AACD6F108C} = {32A813F5-13B2-4DCA-8B59-F27F1B0D5678}
+ {B758A87D-0BFA-44A5-BA33-FBA44151CEB4} = {32A813F5-13B2-4DCA-8B59-F27F1B0D5678}
+ {DEA3342F-1954-4EE9-9A59-CAF1D7832F33} = {B758A87D-0BFA-44A5-BA33-FBA44151CEB4}
+ {86C82BB6-E333-40E8-8DDE-20C3A538433C} = {B758A87D-0BFA-44A5-BA33-FBA44151CEB4}
+ {679625DD-4BF6-4CD6-99FD-7A3E6D9B04A1} = {B758A87D-0BFA-44A5-BA33-FBA44151CEB4}
+ {A8043204-9DAC-4F08-8C73-423CB72927EF} = {B758A87D-0BFA-44A5-BA33-FBA44151CEB4}
+ {83BE964D-D53C-4D1B-B8C6-5306C393C07F} = {B758A87D-0BFA-44A5-BA33-FBA44151CEB4}
+ {959A33C5-7826-4AE7-AC51-40BDC2B767B2} = {B758A87D-0BFA-44A5-BA33-FBA44151CEB4}
+ {07C9E949-DB5E-4315-A497-FF73746667D8} = {32A813F5-13B2-4DCA-8B59-F27F1B0D5678}
+ {5467178B-3731-4346-A0A3-3CB1AC0953AB} = {07C9E949-DB5E-4315-A497-FF73746667D8}
+ {2E082104-D3A6-40DE-A4E5-DE326B75A62D} = {07C9E949-DB5E-4315-A497-FF73746667D8}
+ {ECF1AA6F-8FCD-428F-9648-2DAE3C345C96} = {07C9E949-DB5E-4315-A497-FF73746667D8}
+ {478DA36E-F547-49CD-8B48-41DC5551C5C2} = {07C9E949-DB5E-4315-A497-FF73746667D8}
+ {2074EA00-59A4-49CE-97A6-735F4B77443B} = {07C9E949-DB5E-4315-A497-FF73746667D8}
+ {0C031C7D-6F80-4559-977C-AC001036EC44} = {07C9E949-DB5E-4315-A497-FF73746667D8}
+ {60E54034-792C-4A90-BCDF-4D5FFB45089E} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}
+ {FC559052-36EC-4379-B447-298FAD6045F4} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}
+ {8A604A6B-D1FA-4CFF-BCF5-557519B10FCB} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}
+ {1BF3115D-B027-4805-AF7B-41B3AE9CB355} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}
+ {590B1EC0-CDA9-4937-BE07-FBB04437D21F} = {5F2B846D-96CE-400A-878E-220498F4EE31}
+ {8941B30D-698B-477A-8737-43E7B4A8695A} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}
+ {063178CF-C5B9-463C-A8A4-F32B743818E2} = {EEF5F221-0E32-4A3D-B647-B4B5E7305806}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {6C1A3808-0F4F-43FB-A9FE-5F27A3BB2ECF}
+ EndGlobalSection
+EndGlobal
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Extensions/HttpContextExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Extensions/HttpContextExtensions.cs
new file mode 100644
index 00000000..b16e5509
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Extensions/HttpContextExtensions.cs
@@ -0,0 +1,99 @@
+using Microsoft.AspNetCore.Http;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.AspNetCore.Extensions
+{
+ public static class HttpContextExtensions
+ {
+ ///
+ /// 设置文件下载名称
+ ///
+ ///
+ ///
+ public static void FileInlineHandle(this HttpContext httpContext, string fileName)
+ {
+ string encodeFilename = System.Web.HttpUtility.UrlEncode(fileName, Encoding.GetEncoding("UTF-8"));
+ httpContext.Response.Headers.Add("Content-Disposition", "inline;filename=" + encodeFilename);
+
+ }
+
+ ///
+ /// 设置文件附件名称
+ ///
+ ///
+ ///
+ public static void FileAttachmentHandle(this HttpContext httpContext, string fileName)
+ {
+ string encodeFilename = System.Web.HttpUtility.UrlEncode(fileName, Encoding.GetEncoding("UTF-8"));
+ httpContext.Response.Headers.Add("Content-Disposition", "attachment;filename=" + encodeFilename);
+
+ }
+
+ ///
+ /// 获取语言种类
+ ///
+ ///
+ ///
+ public static string GetLanguage(this HttpContext httpContext)
+ {
+ string res = "zh-CN";
+ var str = httpContext.Request.Headers["Accept-Language"].FirstOrDefault();
+ if (str is not null)
+ {
+ res = str.Split(",")[0];
+ }
+ return res;
+
+ }
+
+ ///
+ /// 判断是否为异步请求
+ ///
+ ///
+ ///
+ public static bool IsAjaxRequest(this HttpRequest request)
+ {
+ string header = request.Headers["X-Requested-With"];
+ return "XMLHttpRequest".Equals(header);
+ }
+ ///
+ /// 获取客户端IP
+ ///
+ ///
+ ///
+ public static string GetClientIp(this HttpContext context)
+ {
+ if (context == null) return "";
+ var result = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
+ if (string.IsNullOrEmpty(result))
+ {
+ result = context.Connection.RemoteIpAddress?.ToString();
+ }
+ if (string.IsNullOrEmpty(result) || result.Contains("::1"))
+ result = "127.0.0.1";
+
+ result = result.Replace("::ffff:", "127.0.0.1");
+
+ //Ip规则效验
+ var regResult = Regex.IsMatch(result, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
+
+ result = regResult ? result : "127.0.0.1";
+ return result;
+ }
+
+ ///
+ /// 获取浏览器标识
+ ///
+ ///
+ ///
+ public static string GetUserAgent(this HttpContext context)
+ {
+ return context.Request.Headers["User-Agent"];
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/CorsUseExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/CorsUseExtensions.cs
new file mode 100644
index 00000000..e4e85233
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/CorsUseExtensions.cs
@@ -0,0 +1,18 @@
+using Microsoft.AspNetCore.Builder;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AspNetCore.Microsoft.AspNetCore.Builder
+{
+ public static class CorsUseExtensions
+ {
+ public static void UseCorsServer(this IApplicationBuilder app)
+ {
+ app.UseCors("CorsPolicy");
+ }
+
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/ErrorHandExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/ErrorHandExtensions.cs
new file mode 100644
index 00000000..85b05dc7
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/ErrorHandExtensions.cs
@@ -0,0 +1,109 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Enums;
+using Yi.Framework.Core.Exceptions;
+
+namespace Microsoft.AspNetCore.Builder
+{
+
+ internal class ExceptionModle
+ {
+ public int Code { get; set; }
+ public string? Message { get; set; }
+ public string? Details { get; set; }
+ }
+ 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 InvokeAsync(HttpContext context)
+ {
+ try
+ {
+ await _next(context);
+ }
+ catch (BusinessException businessEx)
+ {
+ context.Response.ContentType = "application/json;charset=utf-8";
+ context.Response.StatusCode = (int)ResultCodeEnum.Denied;
+
+ var result = new ExceptionModle
+ {
+ Code = businessEx.Code.GetHashCode(),
+ Message = businessEx.Message,
+ Details = businessEx.Details,
+ };
+ //业务错误,不记录日志
+ await context.Response.WriteAsync(JsonConvert.SerializeObject(result, new JsonSerializerSettings()
+ {
+ //设置首字母小写
+ ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
+ }));
+
+ }
+ catch (AuthException ex)
+ {
+ context.Response.ContentType = "application/json;charset=utf-8";
+ //系统错误,记录日志
+ _logger.LogError(ex, $"授权失败:{ex.Message}");
+ //await _errorHandle.Invoer(context, ex);
+ context.Response.StatusCode = (int)ResultCodeEnum.NoPermission;
+ //系统错误,需要记录
+ var result = new ExceptionModle
+ {
+ Code = ex.Code.GetHashCode(),
+ Message = ex.Message,
+ Details = "授权失败",
+ };
+ await context.Response.WriteAsync(JsonConvert.SerializeObject(result, new JsonSerializerSettings()
+ {
+ //设置首字母小写
+ ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
+ }));
+
+ }
+ catch (Exception ex)
+ {
+ context.Response.ContentType = "application/json;charset=utf-8";
+ //系统错误,记录日志
+ _logger.LogError(ex, $"系统错误:{ex.Message}");
+ //await _errorHandle.Invoer(context, ex);
+ context.Response.StatusCode = (int)ResultCodeEnum.NotSuccess;
+ //系统错误,需要记录
+ var result = new ExceptionModle
+ {
+ Code = 500,
+ Message = ex.Message,
+ Details = "系统错误",
+ };
+ await context.Response.WriteAsync(JsonConvert.SerializeObject(result, new JsonSerializerSettings()
+ {
+ //设置首字母小写
+ ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
+ }));
+ }
+ }
+
+ }
+
+ public static class ErrorHandExtensions
+ {
+ public static IApplicationBuilder UseErrorHandlingServer(this IApplicationBuilder builder)
+ {
+ return builder.UseMiddleware();
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/SwaggerUseExtensons.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/SwaggerUseExtensons.cs
new file mode 100644
index 00000000..cf37af7b
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/SwaggerUseExtensons.cs
@@ -0,0 +1,55 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Swashbuckle.AspNetCore.SwaggerUI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AspNetCore.Microsoft.AspNetCore.Builder
+{
+ public static class SwaggerUseExtensons
+ {
+ public static IApplicationBuilder UseSwaggerServer(this IApplicationBuilder app, params SwaggerModel[] swaggerModels)
+ {
+
+ app.UseSwagger();
+ app.UseSwaggerUI(c =>
+ {
+ if (swaggerModels.Length == 0)
+ {
+ c.SwaggerEndpoint("/swagger/v1/swagger.json", "Yi.Framework");
+ }
+ else
+ {
+ foreach (var k in swaggerModels)
+ {
+
+ c.SwaggerEndpoint(k.Url, k.Name);
+ }
+ }
+
+ });
+ return app;
+ }
+
+ }
+ public class SwaggerModel
+ {
+ public SwaggerModel(string name)
+ {
+ this.Name = name;
+ this.Url = "/swagger/v1/swagger.json";
+ }
+ public SwaggerModel(string url, string name)
+ {
+ this.Url = url;
+ this.Name = name;
+ }
+ public string Url { get; set; }
+ public string Name { get; set; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Hosting/StratUrlsExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Hosting/StratUrlsExtensions.cs
new file mode 100644
index 00000000..3076545d
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Hosting/StratUrlsExtensions.cs
@@ -0,0 +1,19 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AspNetCore.Microsoft.AspNetCore.Hosting
+{
+ public static class StratUrlsExtensions
+ {
+ public static IWebHostBuilder UseStartUrlsServer(this IWebHostBuilder hostBuilder, IConfiguration configuration, string option = "StartUrl")
+ {
+ return hostBuilder.UseUrls(configuration.GetValue(option));
+ }
+
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/ControllerAddExtension.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/ControllerAddExtension.cs
new file mode 100644
index 00000000..cb17808a
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/ControllerAddExtension.cs
@@ -0,0 +1,25 @@
+using Microsoft.Extensions.DependencyInjection;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection
+{
+ public static class ControllerAddExtension
+ {
+ public static IMvcBuilder AddNewtonsoftJsonServer(this IMvcBuilder mvcBuilder)
+ {
+ return mvcBuilder.AddNewtonsoftJson(opt =>
+ {
+ //忽略循环引用
+ opt.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+ //不改变字段大小
+ //opt.SerializerSettings.ContractResolver = new DefaultContractResolver();
+ });
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CorsAddExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CorsAddExtensions.cs
new file mode 100644
index 00000000..56daefe6
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CorsAddExtensions.cs
@@ -0,0 +1,25 @@
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.Extensions.DependencyInjection
+{
+ public static class CorsAddExtensions
+ {
+ public static IServiceCollection AddCorsServer(this IServiceCollection services)
+ {
+ services.AddCors(options => options.AddPolicy("CorsPolicy",
+ builder =>
+ {
+ builder.AllowAnyMethod()
+ .SetIsOriginAllowed(_ => true)
+ .AllowAnyHeader()
+ .AllowCredentials();
+ }));
+ return services;
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CurrentUserAddExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CurrentUserAddExtensions.cs
new file mode 100644
index 00000000..e6874c1a
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CurrentUserAddExtensions.cs
@@ -0,0 +1,32 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Const;
+using Yi.Framework.Core.CurrentUsers;
+using Yi.Framework.Core.CurrentUsers.Accessor;
+
+namespace Microsoft.Extensions.DependencyInjection
+{
+ public static class CurrentUserAddExtensions
+ {
+ public static IServiceCollection AddCurrentUserServer(this IServiceCollection services)
+ {
+ services.AddSingleton();
+ return services.AddTransient();
+ }
+
+
+
+ }
+
+
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/SwaggerAddExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/SwaggerAddExtensions.cs
new file mode 100644
index 00000000..16932d90
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/SwaggerAddExtensions.cs
@@ -0,0 +1,61 @@
+using Microsoft.Extensions.Options;
+using Microsoft.OpenApi.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+
+namespace Microsoft.Extensions.DependencyInjection
+{
+ public static class SwaggerAddExtensions
+ {
+ public static IServiceCollection AddSwaggerServer(this IServiceCollection services, string title = "Yi意框架-API接口")
+ {
+ var apiInfo = new OpenApiInfo
+ {
+ Title = title,
+ Version = "v1",
+ Contact = new OpenApiContact { Name = "橙子", Email = "454313500@qq.com", Url = new Uri("https://ccnetcore.com") }
+ };
+ #region 注册Swagger服务
+ services.AddSwaggerGen(c =>
+ {
+ c.DocInclusionPredicate((docName, description) => true);
+
+ c.SwaggerDoc("v1", apiInfo);
+
+
+ var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);
+ if (basePath is not null)
+ {
+ foreach (var item in Directory.GetFiles(basePath, "*.xml"))
+ {
+ c.IncludeXmlComments(item, true);
+ }
+ }
+
+ c.AddSecurityDefinition("JwtBearer", new OpenApiSecurityScheme()
+ {
+ Description = "直接输入Token即可",
+ Name = "Authorization",
+ In = ParameterLocation.Header,
+ Type = SecuritySchemeType.Http,
+ Scheme = "bearer"
+ });
+ var scheme = new OpenApiSecurityScheme()
+ {
+ Reference = new OpenApiReference() { Type = ReferenceType.SecurityScheme, Id = "JwtBearer" }
+ };
+ c.AddSecurityRequirement(new OpenApiSecurityRequirement()
+ {
+ [scheme] = new string[0]
+ });
+ });
+ #endregion
+
+ return services;
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj
new file mode 100644
index 00000000..c37d68fb
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj
@@ -0,0 +1,25 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs
new file mode 100644
index 00000000..85f7cba7
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs
@@ -0,0 +1,29 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using StartupModules;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.CurrentUsers.Accessor;
+using Yi.Framework.Core.CurrentUsers;
+
+namespace Yi.Framework.AspNetCore
+{
+ public class YiFrameworkAspNetCoreModule : IStartupModule
+ {
+
+ public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context)
+ {
+ }
+
+ public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context)
+ {
+ services.AddHttpContextAccessor();
+ services.AddCurrentUserServer();
+
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/JwtTokenManager.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/JwtTokenManager.cs
new file mode 100644
index 00000000..70974444
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/JwtTokenManager.cs
@@ -0,0 +1,100 @@
+using JWT;
+using JWT.Algorithms;
+using JWT.Builder;
+using JWT.Exceptions;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Auth.JwtBearer.Authentication.Options;
+using Yi.Framework.Core.Helper;
+
+namespace Yi.Framework.Auth.JwtBearer.Authentication
+{
+ public class JwtTokenManager
+ {
+ private JwtTokenOptions _jwtTokenOptions;
+
+ public JwtTokenManager(IOptions options)
+ {
+ _jwtTokenOptions = options.Value;
+ }
+ public string CreateToken(Dictionary? claimDic)
+ {
+ var token = JwtBuilder.Create()
+ .WithAlgorithm(new RS256Algorithm(RSAFileHelper.GetKey(), RSAFileHelper.GetKey()))
+ .AddClaim(ClaimName.Issuer, _jwtTokenOptions.Issuer)
+ .AddClaim(ClaimName.Audience, _jwtTokenOptions.Audience)
+ .AddClaim(ClaimName.Subject, _jwtTokenOptions.Subject)
+ .AddClaim(ClaimName.IssuedAt, UnixEpoch.GetSecondsSince(new DateTimeOffset(DateTime.UtcNow)))
+ .ExpirationTime(DateTime.Now.AddSeconds(_jwtTokenOptions.ExpSecond));
+ if (claimDic is not null)
+ {
+ foreach (var d in claimDic)
+ {
+ token.AddClaim(d.Key, d.Value);
+ };
+ }
+ return token.Encode();
+ }
+
+ public IDictionary? VerifyToken(string token, TokenVerifyErrorAction tokenVerifyErrorAction)
+ {
+ IDictionary? claimDic = null;
+ try
+ {
+
+ claimDic = JwtBuilder.Create()
+ .WithAlgorithm(new RS256Algorithm(RSAFileHelper.GetPublicKey()))
+ .WithValidationParameters(ValidationParameters.Default)
+ .Decode>(token);
+ }
+ catch (TokenNotYetValidException ex)
+ {
+ if (tokenVerifyErrorAction.TokenNotYetValidAction is not null)
+ {
+ tokenVerifyErrorAction.TokenNotYetValidAction(ex);
+ }
+ //Console.WriteLine("Token错误");
+ }
+ catch (TokenExpiredException ex)
+ {
+ if (tokenVerifyErrorAction.TokenExpiredAction is not null)
+ {
+ tokenVerifyErrorAction.TokenExpiredAction(ex);
+ }
+ //Console.WriteLine("Token过期");
+ }
+ catch (SignatureVerificationException ex)
+ {
+ if (tokenVerifyErrorAction.SignatureVerificationAction is not null)
+ {
+ tokenVerifyErrorAction.SignatureVerificationAction(ex);
+ }
+ //Console.WriteLine("Token无效");
+ }
+ catch (Exception ex)
+ {
+ if (tokenVerifyErrorAction.ErrorAction is not null)
+ {
+ tokenVerifyErrorAction.ErrorAction(ex);
+ }
+ //Console.WriteLine("Token内部错误,json序列化");
+ }
+ return claimDic;
+
+ }
+
+ public class TokenVerifyErrorAction
+ {
+ public Action? TokenNotYetValidAction { get; set; }
+
+ public Action? TokenExpiredAction { get; set; }
+ public Action? SignatureVerificationAction { get; set; }
+
+ public Action? ErrorAction { get; set; }
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/Options/JwtTokenOptions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/Options/JwtTokenOptions.cs
new file mode 100644
index 00000000..c2643148
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/Options/JwtTokenOptions.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Auth.JwtBearer.Authentication.Options
+{
+ public class JwtTokenOptions
+ {
+ ///
+ /// 听众
+ ///
+ public string Audience { get; set; } = string.Empty;
+
+ ///
+ /// 发行者
+ ///
+ public string Issuer { get; set; } = string.Empty;
+
+ ///
+ /// 主题
+ ///
+ public string Subject { get; set; } = string.Empty;
+
+ ///
+ /// 过期时间,单位秒
+ ///
+ public long ExpSecond { get; set; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/YiJwtAuthenticationHandler.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/YiJwtAuthenticationHandler.cs
new file mode 100644
index 00000000..332fa901
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/YiJwtAuthenticationHandler.cs
@@ -0,0 +1,132 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+using System.Net;
+using System.Security.Claims;
+using System.Text.Json;
+using Yi.Framework.Core.Helper;
+
+namespace Yi.Framework.Auth.JwtBearer.Authentication
+{
+ public class YiJwtAuthenticationHandler : IAuthenticationHandler
+ {
+ private JwtTokenManager _jwtTokenManager;
+ public YiJwtAuthenticationHandler(JwtTokenManager jwtTokenManager)
+ {
+ _jwtTokenManager = jwtTokenManager;
+ }
+ public const string YiJwtSchemeName = "YiJwtAuth";
+
+ private AuthenticationScheme _scheme;
+ private HttpContext _context;
+ ///
+ /// 初始化数据
+ ///
+ ///
+ ///
+ ///
+ public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
+ {
+ _scheme = scheme;
+ _context = context;
+ return Task.CompletedTask;
+ }
+
+
+ ///
+ /// 生成认证票据
+ ///
+ ///
+ ///
+ ///
+ private AuthenticationTicket GetAuthTicket(IDictionary dicClaims)
+ {
+ List claims = new List();
+ foreach (var claim in dicClaims)
+ {
+ var p = (JsonElement)claim.Value;
+ string? resp=null;
+ switch (p.ValueKind)
+ {
+
+ case JsonValueKind.String:
+ resp = p.GetString();
+ break;
+ case JsonValueKind.Number:
+ resp = p.GetInt64().ToString();
+ break;
+ }
+ claims.Add(new Claim(claim.Key, resp ?? ""));
+ }
+ var claimsIdentity = new ClaimsIdentity(claims.ToArray(), YiJwtSchemeName);
+ var principal = new ClaimsPrincipal(claimsIdentity);
+ return new AuthenticationTicket(principal, _scheme.Name);
+ }
+
+ ///
+ /// 处理操作
+ ///
+ ///
+ ///
+ public Task AuthenticateAsync()
+ {
+ AuthenticateResult result = AuthenticateResult.Fail("未发现授权令牌");
+ _context.Request.Headers.TryGetValue("Authorization", out StringValues values);
+ string valStr = values.ToString();
+ if (!string.IsNullOrWhiteSpace(valStr) && valStr.Length>10)
+ {
+ var tokenHeader = valStr.Substring(0, 6);
+ if (tokenHeader == "Bearer")
+ {
+ var token = valStr.Substring(7);
+
+ var claimDic = _jwtTokenManager.VerifyToken(token, new JwtTokenManager.TokenVerifyErrorAction()
+ {
+ TokenExpiredAction = (ex) => { result = AuthenticateResult.Fail("Token过期"); },
+ SignatureVerificationAction = (ex) => { result = AuthenticateResult.Fail("Token效验失效"); },
+ TokenNotYetValidAction = (ex) => { result = AuthenticateResult.Fail("Token完全错误"); },
+ ErrorAction = (ex) => { result = AuthenticateResult.Fail("Token内部错误"); }
+ });
+ if (claimDic is not null)
+ {
+ //成功
+ result = AuthenticateResult.Success(GetAuthTicket(claimDic));
+ }
+ }
+ else
+ {
+ result = AuthenticateResult.Fail("授权令牌格式错误");
+ }
+
+ }
+ return Task.FromResult(result);
+ }
+
+ ///
+ /// 未登录时的处理
+ ///
+ ///
+ ///
+ ///
+ public Task ChallengeAsync(AuthenticationProperties? properties)
+ {
+ _context.Request.Headers.TryGetValue("Authorization", out StringValues values);
+ _context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// 权限不足的处理
+ ///
+ ///
+ ///
+ ///
+ public Task ForbidAsync(AuthenticationProperties? properties)
+ {
+ _context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
+ return Task.CompletedTask;
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/DefaultPermissionHandler.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/DefaultPermissionHandler.cs
new file mode 100644
index 00000000..4aad26a0
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/DefaultPermissionHandler.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.CurrentUsers;
+
+namespace Yi.Framework.Auth.JwtBearer.Authorization
+{
+ public class DefaultPermissionHandler : IPermissionHandler
+ {
+ private ICurrentUser _currentUser { get; set; }
+
+ public DefaultPermissionHandler(ICurrentUser currentUser)
+ {
+ _currentUser = currentUser;
+ }
+ public bool IsPass(string permission)
+ {
+ if (_currentUser.Permission is not null)
+ {
+ return _currentUser.Permission.Contains(permission);
+
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/IPermissionHandler.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/IPermissionHandler.cs
new file mode 100644
index 00000000..4cc17784
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/IPermissionHandler.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.CurrentUsers;
+
+namespace Yi.Framework.Auth.JwtBearer.Authorization
+{
+ public interface IPermissionHandler
+ {
+ bool IsPass(string permission );
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionAttribute.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionAttribute.cs
new file mode 100644
index 00000000..475d3180
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionAttribute.cs
@@ -0,0 +1,29 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.CurrentUsers;
+using Yi.Framework.Core.Exceptions;
+using Yi.Framework.Core.Model;
+
+namespace Yi.Framework.Auth.JwtBearer.Authorization
+{
+
+ [AttributeUsage(AttributeTargets.Method)]
+
+ public class PermissionAttribute : ActionFilterAttribute
+ {
+ internal string Code { get; set; }
+
+ public PermissionAttribute(string code)
+ {
+ this.Code = code;
+ }
+
+
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionGlobalAttribute.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionGlobalAttribute.cs
new file mode 100644
index 00000000..06e7d17d
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionGlobalAttribute.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Yi.Framework.Auth.JwtBearer.Authorization;
+using Yi.Framework.Core.Exceptions;
+
+namespace SF.AspNetCore.Auth.Authorization;
+public class PermissionGlobalAttribute : ActionFilterAttribute
+{
+ private readonly IPermissionHandler _permissionHandler;
+ public PermissionGlobalAttribute(IPermissionHandler permissionHandler)
+ {
+ _permissionHandler=permissionHandler;
+ }
+ public override void OnActionExecuting(ActionExecutingContext context)
+ {
+ if (context.ActionDescriptor is not ControllerActionDescriptor controllerActionDescriptor) return;
+ PermissionAttribute? perAttribute = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
+ .FirstOrDefault(a => a.GetType().Equals(typeof(PermissionAttribute))) as PermissionAttribute;
+ //空对象直接返回
+ if (perAttribute is null) return;
+
+ var result = _permissionHandler.IsPass(perAttribute.Code);
+
+ if (!result)
+ {
+ throw new AuthException(message: $"您无权限访问该接口-{context.HttpContext.Request.Path.Value}");
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Yi.Framework.Auth.JwtBearer.csproj b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Yi.Framework.Auth.JwtBearer.csproj
new file mode 100644
index 00000000..00bb5f5e
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Yi.Framework.Auth.JwtBearer.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/YiFrameworkAuthJwtBearerModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/YiFrameworkAuthJwtBearerModule.cs
new file mode 100644
index 00000000..dbddcffe
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/YiFrameworkAuthJwtBearerModule.cs
@@ -0,0 +1,47 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using SF.AspNetCore.Auth.Authorization;
+using StartupModules;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Auth.JwtBearer.Authentication;
+using Yi.Framework.Auth.JwtBearer.Authentication.Options;
+using Yi.Framework.Auth.JwtBearer.Authorization;
+using Yi.Framework.Core;
+using Yi.Framework.Core.Attributes;
+using Yi.Framework.Core.Configuration;
+
+namespace Yi.Framework.Auth.JwtBearer
+{
+ [DependsOn(typeof(YiFrameworkCoreModule))]
+ public class YiFrameworkAuthJwtBearerModule : IStartupModule
+ {
+ public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context)
+ {
+ }
+
+ public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context)
+ {
+ services.Configure(Appsettings.appConfiguration("JwtTokenOptions"));
+ services.AddAuthentication(YiJwtAuthenticationHandler.YiJwtSchemeName);
+ services.AddTransient();
+ services.AddSingleton();
+ services.AddAuthentication(option =>
+ {
+ option.AddScheme(YiJwtAuthenticationHandler.YiJwtSchemeName, YiJwtAuthenticationHandler.YiJwtSchemeName);
+ });
+ services.AddSingleton();
+ services.AddControllers(options => {
+ options.Filters.Add();
+ });
+ //services.AddSingleton();
+ //services.AddControllers(options => {
+ // options.Filters.Add();
+ //});
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.AutoMapper/Yi.Framework.Core.Mapster.csproj b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.AutoMapper/Yi.Framework.Core.Mapster.csproj
new file mode 100644
index 00000000..6202c43e
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.AutoMapper/Yi.Framework.Core.Mapster.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.AutoMapper/YiFrameworkCoreMapsterModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.AutoMapper/YiFrameworkCoreMapsterModule.cs
new file mode 100644
index 00000000..396d6b3d
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.AutoMapper/YiFrameworkCoreMapsterModule.cs
@@ -0,0 +1,26 @@
+using MapsterMapper;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+using StartupModules;
+using Yi.Framework.Core.Attributes;
+
+namespace Yi.Framework.Core.AutoMapper
+{
+ [DependsOn(
+ typeof(YiFrameworkCoreModule)
+ )]
+ public class YiFrameworkCoreMapsterModule : IStartupModule
+ {
+
+ public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context)
+ {
+ }
+
+ public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context)
+ {
+
+ //添加全局自动mapper
+ services.AddSingleton();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Extensions/AutoFacExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Extensions/AutoFacExtensions.cs
new file mode 100644
index 00000000..1afba5bf
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Extensions/AutoFacExtensions.cs
@@ -0,0 +1,27 @@
+using Autofac;
+using Autofac.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Autofac.Extensions
+{
+ public static class AutoFacExtensions
+ {
+ public static IHostBuilder UseAutoFacServerProviderFactory(this IHostBuilder hostBuilder)
+ {
+ hostBuilder.UseServiceProviderFactory(new AutofacServiceProviderFactory());
+
+ return hostBuilder;
+ }
+
+ public static IHostBuilder ConfigureAutoFacContainer(this IHostBuilder hostBuilder, Action configureDelegate)
+ {
+ hostBuilder.UseAutoFacServerProviderFactory();
+ return hostBuilder.ConfigureContainer(configureDelegate);
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Extensions/AutoFacModuleExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Extensions/AutoFacModuleExtensions.cs
new file mode 100644
index 00000000..bd87fdca
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Extensions/AutoFacModuleExtensions.cs
@@ -0,0 +1,35 @@
+using Autofac;
+using Autofac.Core.Registration;
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Autofac.Modules;
+
+namespace Yi.Framework.Core.Autofac.Extensions
+{
+ public static class AutoFacModuleExtensions
+ {
+ public static void RegisterYiModule(this ContainerBuilder builder, params Assembly[] assemblies) where TModule : YiAutoFacModule, new()
+ {
+ new TModule().Load(builder, assemblies);
+ }
+
+
+ public static void RegisterYiModule(this ContainerBuilder builder, AutoFacModuleEnum autoFacModuleEnum, params Assembly[] assemblies)
+ {
+ Logger? _logger = LogManager.Setup().LoadConfigurationFromAssemblyResource(typeof(AutoFacModuleExtensions).Assembly).GetCurrentClassLogger();
+ switch (autoFacModuleEnum)
+ {
+ case AutoFacModuleEnum.PropertiesAutowiredModule:
+ _logger.Info($"意框架添加AutoFac模块:{nameof(PropertiesAutowiredModule)}-属性注入模块");
+ new PropertiesAutowiredModule().Load(builder, assemblies);
+ break;
+ }
+ }
+
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Modules/AutoFacModuleEnum.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Modules/AutoFacModuleEnum.cs
new file mode 100644
index 00000000..8b25c34b
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Modules/AutoFacModuleEnum.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.Autofac.Modules
+{
+ public enum AutoFacModuleEnum
+ {
+ PropertiesAutowiredModule
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Modules/PropertiesAutowiredModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Modules/PropertiesAutowiredModule.cs
new file mode 100644
index 00000000..289dd8c2
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Modules/PropertiesAutowiredModule.cs
@@ -0,0 +1,32 @@
+using Autofac;
+using Autofac.Core;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Attributes;
+
+
+namespace Yi.Framework.Core.Autofac.Modules
+{
+ internal class PropertiesAutowiredModule : YiAutoFacModule
+ {
+ internal override void Load(ContainerBuilder containerBuilder, params Assembly[] assemblies)
+ {
+ containerBuilder.RegisterAssemblyTypes(assemblies)
+ .PropertiesAutowired(new AutowiredPropertySelector());
+ }
+
+ }
+
+ public class AutowiredPropertySelector : IPropertySelector
+ {
+ public bool InjectProperty(PropertyInfo propertyInfo, object instance)
+ {
+ return propertyInfo.CustomAttributes.Any(it => it.AttributeType == typeof(AutowiredAttribute));
+ }
+ }
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Modules/YiAutoFacModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Modules/YiAutoFacModule.cs
new file mode 100644
index 00000000..68d60f6c
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Modules/YiAutoFacModule.cs
@@ -0,0 +1,15 @@
+using Autofac;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Autofac.Modules
+{
+ public abstract class YiAutoFacModule
+ {
+ internal abstract void Load(ContainerBuilder containerBuilder,params Assembly[] assemblies);
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Properties/launchSettings.json b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Properties/launchSettings.json
new file mode 100644
index 00000000..a8b2dde8
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Properties/launchSettings.json
@@ -0,0 +1,12 @@
+{
+ "profiles": {
+ "Yi.Framework.Autofac": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:53043;http://localhost:53044"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Yi.Framework.Core.Autofac.csproj b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Yi.Framework.Core.Autofac.csproj
new file mode 100644
index 00000000..d30b69ea
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/Yi.Framework.Core.Autofac.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/YiFrameworkCoreAutofacModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/YiFrameworkCoreAutofacModule.cs
new file mode 100644
index 00000000..19467e7b
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Autofac/YiFrameworkCoreAutofacModule.cs
@@ -0,0 +1,27 @@
+using Autofac.Core;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using StartupModules;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Autofac
+{
+ public class YiFrameworkCoreAutofacModule : IStartupModule
+ {
+ public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context)
+ {
+ }
+
+ public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context)
+ {
+ //将控制器交由autofac注册
+ services.Replace(ServiceDescriptor.Transient());
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Const/SqlsugarConst.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Const/SqlsugarConst.cs
new file mode 100644
index 00000000..274024ae
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Const/SqlsugarConst.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Sqlsugar.Const
+{
+ public class SqlsugarConst
+ {
+ public const string 读写分离为空 = "开启读写分离后,读库连接不能为空";
+
+ public const string DbType配置为空 = "DbType配置为空,必须选择一个数据库类型";
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarCodeFirstExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarCodeFirstExtensions.cs
new file mode 100644
index 00000000..c9bd3f08
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarCodeFirstExtensions.cs
@@ -0,0 +1,61 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Sqlsugar.Options;
+
+namespace Yi.Framework.Core.Sqlsugar.Extensions
+{
+ public static class SqlsugarCodeFirstExtensions
+ {
+ public static void UseSqlsugarCodeFirstServer(this IApplicationBuilder app)
+ {
+ var db = app.ApplicationServices.GetRequiredService();
+ var options = app.ApplicationServices.GetRequiredService>();
+
+ if (options.Value.EnabledCodeFirst == false) return;
+
+ db.DbMaintenance.CreateDatabase();
+ var assemblys = new List();
+
+ //全盘加载
+ if (options.Value.EntityAssembly is null)
+ {
+ assemblys.AddRange(AppDomain.CurrentDomain.GetAssemblies().ToList());
+ }
+ //按需加载
+ else
+ {
+ options.Value.EntityAssembly.ForEach(a =>
+ {
+ assemblys.Add(Assembly.Load(a));
+ });
+ }
+
+ foreach (var assembly in assemblys)
+ {
+ TableInvoer(db, assembly.GetTypes().ToList());
+ }
+
+ }
+
+ private static void TableInvoer(ISqlSugarClient _Db, List typeList)
+ {
+ foreach (var t in typeList)
+ {
+ //扫描如果存在SugarTable特性 并且 不是分表模型,直接codefirst
+ if (t.GetCustomAttributes(false).Any(a => a.GetType().Equals(typeof(SugarTable))
+ && !t.GetCustomAttributes(false).Any(a => a.GetType().Equals(typeof(SplitTableAttribute)))))
+ {
+ _Db.CodeFirst.SetStringDefaultLength(200).InitTables(t);//这样一个表就能成功创建了
+ }
+ }
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarDataFiterExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarDataFiterExtensions.cs
new file mode 100644
index 00000000..e6a96ce3
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarDataFiterExtensions.cs
@@ -0,0 +1,37 @@
+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;
+
+namespace Yi.Framework.Core.Sqlsugar.Extensions
+{
+ public static class SqlsugarDataFilterExtensions
+ {
+ public static IApplicationBuilder UseSqlsugarDataFiterServer(this IApplicationBuilder builder)
+ {
+ return builder.UseMiddleware();
+ }
+ }
+
+ public class SqlsugarDataFilterMiddleware
+ {
+ private readonly RequestDelegate _next;
+ private readonly ILogger _logger;
+ public SqlsugarDataFilterMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
+ {
+ this._next = next;
+ this._logger = loggerFactory.CreateLogger();
+ }
+ public async Task InvokeAsync(HttpContext context)
+ {
+
+ await _next(context);
+
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarExtensions.cs
new file mode 100644
index 00000000..165d8eea
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarExtensions.cs
@@ -0,0 +1,159 @@
+using Autofac.Core;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Configuration;
+using Yi.Framework.Core.Model;
+using Yi.Framework.Core.Sqlsugar.Const;
+using Yi.Framework.Core.Sqlsugar.Options;
+using Yi.Framework.Data.Auditing;
+using Yi.Framework.Data.Entities;
+using DbType = SqlSugar.DbType;
+
+namespace Yi.Framework.Core.Sqlsugar.Extensions
+{
+ ///
+ /// 这一块,需要做成上下文对象,会进行重构
+ ///
+ public static class SqlsugarExtensions
+ {
+ //使用上下文对象
+ public static void AddDbSqlsugarContextServer(this IServiceCollection services)
+ {
+ services.AddSingleton(x => x.GetRequiredService().SqlSugarClient);
+ services.AddSingleton();
+ }
+
+ //直接使用sqlsugar
+ public static void AddSqlsugarServer(this IServiceCollection services, Action? action = null)
+ {
+ var dbConnOptions = Appsettings.app("DbConnOptions");
+
+ if (dbConnOptions.DbType is null)
+ {
+ throw new ArgumentException(SqlsugarConst.DbType配置为空);
+ }
+ var slavaConFig = new List();
+
+
+
+ if (dbConnOptions.EnabledReadWrite)
+ {
+ if (dbConnOptions.ReadUrl is null)
+ {
+ throw new ArgumentException(SqlsugarConst.读写分离为空);
+ }
+
+ var readCon = dbConnOptions.ReadUrl;
+
+ readCon.ForEach(s =>
+ {
+ //如果是动态saas分库,这里的连接串都不能写死,需要动态添加,这里只配置共享库的连接
+ slavaConFig.Add(new SlaveConnectionConfig() { ConnectionString = s });
+ });
+ }
+
+
+
+
+ SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
+ {
+ //准备添加分表分库
+ DbType = dbConnOptions.DbType ?? DbType.Sqlite,
+ ConnectionString = dbConnOptions.Url,
+ IsAutoCloseConnection = true,
+ MoreSettings = new ConnMoreSettings()
+ {
+ DisableNvarchar = true
+ },
+ SlaveConnectionConfigs = slavaConFig,
+ //设置codefirst非空值判断
+ ConfigureExternalServices = new ConfigureExternalServices
+ {
+ EntityService = (c, p) =>
+ {
+ //高版C#写法 支持string?和string
+ if (new NullabilityInfoContext()
+ .Create(c).WriteState is NullabilityState.Nullable)
+ {
+ p.IsNullable = true;
+ }
+ }
+ }
+ },
+ db =>
+ {
+ //扩展
+ if (action is not null)
+ {
+ action(db);
+ }
+ db.Aop.DataExecuting = (oldValue, entityInfo) =>
+ {
+
+ switch (entityInfo.OperationType)
+ {
+ case DataFilterType.UpdateByObject:
+
+ if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModificationTime)))
+ {
+ entityInfo.SetValue(DateTime.Now);
+ }
+ //if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModifierId)))
+ //{
+ // if (_currentUser != null)
+ // {
+ // entityInfo.SetValue(_currentUser.Id);
+ // }
+ //}
+ break;
+ case DataFilterType.InsertByObject:
+ if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreationTime)))
+ {
+ entityInfo.SetValue(DateTime.Now);
+ }
+ //if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreatorId)))
+ //{
+ // if (_currentUser != null)
+ // {
+ // entityInfo.SetValue(_currentUser.Id);
+ // }
+ //}
+
+ //插入时,需要租户id,先预留
+ if (entityInfo.PropertyName.Equals(nameof(IMultiTenant.TenantId)))
+ {
+ //if (this.CurrentTenant is not null)
+ //{
+ // entityInfo.SetValue(this.CurrentTenant.Id);
+ //}
+ }
+ break;
+ }
+ };
+ db.Aop.OnLogExecuting = (s, p) =>
+ {
+ var _logger = ServiceLocatorModel.Instance?.GetRequiredService>();
+
+ StringBuilder sb = new StringBuilder();
+ sb.Append("执行SQL:" + s.ToString());
+ foreach (var i in p)
+ {
+ sb.Append($"\r\n参数:{i.ParameterName},参数值:{i.Value}");
+ }
+ sb.Append($"\r\n 完整SQL:{UtilMethods.GetSqlString(DbType.MySql, s, p)}");
+ _logger?.LogDebug(sb.ToString());
+ };
+
+ });
+ services.AddSingleton(sqlSugar);//这边是SqlSugarScope用AddSingleton
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Filters/SqlsugarDataFilter.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Filters/SqlsugarDataFilter.cs
new file mode 100644
index 00000000..f01082d4
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Filters/SqlsugarDataFilter.cs
@@ -0,0 +1,50 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Data.Filters;
+
+namespace Yi.Framework.Core.Sqlsugar.Filters
+{
+ public class SqlsugarDataFilter : IDataFilter
+ {
+ private ISqlSugarClient _Db { get; set; }
+ public SqlsugarDataFilter(ISqlSugarClient sqlSugarClient)
+ {
+ _Db = sqlSugarClient;
+ }
+ public void AddFilter(Expression> expression) where TFilter : class
+ {
+ _Db.QueryFilter.AddTableFilter(expression);
+ }
+
+ public IDisposable Disable() where TFilter : class
+ {
+ _Db.QueryFilter.ClearAndBackup();
+ return this;
+ }
+
+ public IDisposable Enable() where TFilter : class
+ {
+ throw new NotImplementedException("暂时没有单独还原过滤器的方式");
+ }
+
+ public bool IsEnabled() where TFilter : class
+ {
+ throw new NotImplementedException("暂时没有判断过滤器的方式");
+ }
+
+ public void RemoveFilter() where TFilter : class
+ {
+ _Db.QueryFilter.Clear();
+ }
+
+ public void Dispose()
+ {
+ _Db.QueryFilter.Restore();
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Options/DbConnOptions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Options/DbConnOptions.cs
new file mode 100644
index 00000000..22a6fcd3
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Options/DbConnOptions.cs
@@ -0,0 +1,47 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Sqlsugar.Options
+{
+ public class DbConnOptions
+ {
+ ///
+ /// 连接字符串,必填
+ ///
+ public string? Url { get; set; }
+
+ ///
+ /// 数据库类型
+ ///
+ public DbType? DbType { get; set; }
+
+ ///
+ /// 开启种子数据
+ ///
+ public bool EnabledDbSeed { get; set; } = false;
+
+ ///
+ /// 开启读写分离
+ ///
+ public bool EnabledReadWrite { get; set; } = false;
+
+ ///
+ /// 开启codefirst
+ ///
+ public bool EnabledCodeFirst { get; set; }=false;
+
+ ///
+ /// 实体程序集
+ ///
+ public List? EntityAssembly { get; set; }
+
+ ///
+ /// 读写分离
+ ///
+ public List? ReadUrl { get; set; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Repositories/SqlsugarRepository.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Repositories/SqlsugarRepository.cs
new file mode 100644
index 00000000..ad59e324
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Repositories/SqlsugarRepository.cs
@@ -0,0 +1,155 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Attributes;
+using Yi.Framework.Core.Enums;
+using Yi.Framework.Core.Helper;
+using Yi.Framework.Data.Entities;
+using Yi.Framework.Ddd.Dtos;
+using Yi.Framework.Ddd.Entities;
+using Yi.Framework.Ddd.Repositories;
+
+namespace Yi.Framework.Core.Sqlsugar.Repositories
+{
+ [AppService(typeof(IRepository<>))]
+ public class SqlsugarRepository : SimpleClient, IRepository where T : class, new()
+ {
+ public SqlsugarRepository(ISqlSugarClient context) : base(context)
+ {
+ }
+ ///
+ /// 注释一下,严格意义这里应该protected,但是我认为 简易程度 与 耦合程度 中是需要进行衡量的
+ ///
+ public ISugarQueryable _DbQueryable => base.AsQueryable();
+
+ protected ISqlSugarClient _Db { get { return Context; } set { } }
+
+ public async Task> GetPageListAsync(Expression> whereExpression, IPagedAndSortedResultRequestDto page)
+ {
+ return await base.GetPageListAsync(whereExpression, new PageModel { PageIndex = page.PageNum, PageSize = page.PageSize });
+ }
+
+ public async Task> GetPageListAsync(Expression> whereExpression, IPagedAndSortedResultRequestDto page, Expression>? orderByExpression = null, OrderByEnum orderByType = OrderByEnum.Asc)
+ {
+ return await base.GetPageListAsync(whereExpression, new PageModel { PageIndex = page.PageNum, PageSize = page.PageSize }, orderByExpression, orderByType.EnumToEnum());
+ }
+
+ public async Task> GetPageListAsync(Expression> whereExpression, IPagedAndSortedResultRequestDto page, string? orderBy, OrderByEnum orderByType = OrderByEnum.Asc)
+ {
+ return await _DbQueryable.Where(whereExpression).OrderByIF(orderBy is not null, orderBy + " " + orderByType.ToString().ToLower()).ToPageListAsync(page.PageNum, page.PageSize);
+ }
+
+
+
+
+ public async Task> GetPageListAsync(Expression> whereExpression, int pageNum,int pageSize)
+ {
+ return await base.GetPageListAsync(whereExpression, new PageModel { PageIndex = pageNum, PageSize = pageSize });
+ }
+
+ public async Task> GetPageListAsync(Expression> whereExpression, int pageNum, int pageSize, Expression>? orderByExpression = null, OrderByEnum orderByType = OrderByEnum.Asc)
+ {
+ return await base.GetPageListAsync(whereExpression, new PageModel { PageIndex = pageNum, PageSize = pageSize }, orderByExpression, orderByType.EnumToEnum());
+ }
+
+ public async Task> GetPageListAsync(Expression> whereExpression, int pageNum, int pageSize, string? orderBy, OrderByEnum orderByType = OrderByEnum.Asc)
+ {
+ return await _DbQueryable.Where(whereExpression).OrderByIF(orderBy is not null, orderBy + " " + orderByType.ToString().ToLower()).ToPageListAsync(pageNum, pageSize);
+ }
+
+
+
+
+
+
+
+ public async Task UpdateIgnoreNullAsync(T updateObj)
+ {
+ return await _Db.Updateable(updateObj).IgnoreColumns(true).ExecuteCommandAsync() > 0;
+ }
+
+ public override async Task DeleteAsync(T deleteObj)
+ {
+ //逻辑删除
+ if (deleteObj is ISoftDelete)
+ {
+ //反射赋值
+ ReflexHelper.SetModelValue(nameof(ISoftDelete.IsDeleted), true, deleteObj);
+ return await UpdateAsync(deleteObj);
+
+ }
+ else
+ {
+ return await base.DeleteAsync(deleteObj);
+
+ }
+ }
+ public override async Task DeleteAsync(List deleteObjs)
+ {
+ if (typeof(ISoftDelete).IsAssignableFrom(typeof(T)))
+ {
+ //反射赋值
+ deleteObjs.ForEach(e => ReflexHelper.SetModelValue(nameof(ISoftDelete.IsDeleted), true, e));
+ return await UpdateRangeAsync(deleteObjs);
+ }
+ else
+ {
+ return await base.DeleteAsync(deleteObjs);
+ }
+ }
+ public override async Task DeleteAsync(Expression> whereExpression)
+ {
+ if (typeof(ISoftDelete).IsAssignableFrom(typeof(T)))
+ {
+ var entities = await GetListAsync(whereExpression);
+ //反射赋值
+ entities.ForEach(e => ReflexHelper.SetModelValue(nameof(ISoftDelete.IsDeleted), true, e));
+ return await UpdateRangeAsync(entities);
+ }
+ else
+ {
+ return await base.DeleteAsync(whereExpression);
+ }
+ }
+ public override async Task DeleteByIdAsync(dynamic id)
+ {
+ if (typeof(ISoftDelete).IsAssignableFrom(typeof(T)))
+ {
+ var entity = await GetByIdAsync(id);
+ //反射赋值
+ ReflexHelper.SetModelValue(nameof(ISoftDelete.IsDeleted), true, entity);
+ return await UpdateAsync(entity);
+ }
+ else
+ {
+ return await _Db.Deleteable().In(id).ExecuteCommandAsync() > 0;
+ }
+
+ }
+ public override async Task DeleteByIdsAsync(dynamic[] ids)
+ {
+ if (typeof(ISoftDelete).IsAssignableFrom(typeof(T)))
+ {
+ var entities = await _DbQueryable.In(ids).ToListAsync();
+ if (entities.Count == 0)
+ {
+ return false;
+ }
+ //反射赋值
+ entities.ForEach(e => ReflexHelper.SetModelValue(nameof(ISoftDelete.IsDeleted), true, e));
+ return await UpdateRangeAsync(entities);
+ }
+ else
+ {
+ return await base.DeleteByIdsAsync(ids);
+ }
+
+ }
+
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/SqlSugarDbContext.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/SqlSugarDbContext.cs
new file mode 100644
index 00000000..6ff158ab
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/SqlSugarDbContext.cs
@@ -0,0 +1,152 @@
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.CurrentUsers;
+using Yi.Framework.Core.Model;
+using Yi.Framework.Core.Sqlsugar.Const;
+using Yi.Framework.Core.Sqlsugar.Options;
+using Yi.Framework.Data.Auditing;
+using Yi.Framework.Data.Entities;
+
+namespace Yi.Framework.Core.Sqlsugar
+{
+ public class SqlSugarDbContext
+ {
+ ///
+ /// SqlSugar 客户端
+ ///
+ public ISqlSugarClient SqlSugarClient { get; set; }
+
+ protected ICurrentUser _currentUser;
+
+ protected ILogger _logger;
+
+ protected IOptions _options;
+
+ public SqlSugarDbContext(IOptions options, ICurrentUser currentUser, ILogger logger)
+ {
+ _currentUser = currentUser;
+ _logger = logger;
+ _options = options;
+ var dbConnOptions = options.Value;
+ #region 组装options
+ if (dbConnOptions.DbType is null)
+ {
+ throw new ArgumentException(SqlsugarConst.DbType配置为空);
+ }
+ var slavaConFig = new List();
+ if (dbConnOptions.EnabledReadWrite)
+ {
+ if (dbConnOptions.ReadUrl is null)
+ {
+ throw new ArgumentException(SqlsugarConst.读写分离为空);
+ }
+
+ var readCon = dbConnOptions.ReadUrl;
+
+ readCon.ForEach(s =>
+ {
+ //如果是动态saas分库,这里的连接串都不能写死,需要动态添加,这里只配置共享库的连接
+ slavaConFig.Add(new SlaveConnectionConfig() { ConnectionString = s });
+ });
+ }
+ #endregion
+ SqlSugarClient = new SqlSugarScope(new ConnectionConfig()
+ {
+ //准备添加分表分库
+ DbType = dbConnOptions.DbType ?? DbType.Sqlite,
+ ConnectionString = dbConnOptions.Url,
+ IsAutoCloseConnection = true,
+ MoreSettings = new ConnMoreSettings()
+ {
+ DisableNvarchar = true
+ },
+ SlaveConnectionConfigs = slavaConFig,
+ //设置codefirst非空值判断
+ ConfigureExternalServices = new ConfigureExternalServices
+ {
+ EntityService = (c, p) =>
+ {
+ //高版C#写法 支持string?和string
+ if (new NullabilityInfoContext()
+ .Create(c).WriteState is NullabilityState.Nullable)
+ {
+ p.IsNullable = true;
+ }
+ }
+ }
+ },
+ db =>
+ {
+
+ db.Aop.DataExecuting = (oldValue, entityInfo) =>
+ {
+
+ switch (entityInfo.OperationType)
+ {
+ case DataFilterType.UpdateByObject:
+
+ if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModificationTime)))
+ {
+ entityInfo.SetValue(DateTime.Now);
+ }
+ if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModifierId)))
+ {
+ if (_currentUser != null)
+ {
+ entityInfo.SetValue(_currentUser.Id);
+ }
+ }
+ break;
+ case DataFilterType.InsertByObject:
+ if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreationTime)))
+ {
+ entityInfo.SetValue(DateTime.Now);
+ }
+ if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreatorId)))
+ {
+ if (_currentUser != null)
+ {
+ entityInfo.SetValue(_currentUser.Id);
+ }
+ }
+
+ //插入时,需要租户id,先预留
+ if (entityInfo.PropertyName.Equals(nameof(IMultiTenant.TenantId)))
+ {
+ //if (this.CurrentTenant is not null)
+ //{
+ // entityInfo.SetValue(this.CurrentTenant.Id);
+ //}
+ }
+ break;
+ }
+ };
+ db.Aop.OnLogExecuting = (s, p) =>
+ {
+ StringBuilder sb = new StringBuilder();
+ //sb.Append("执行SQL:" + s.ToString());
+ //foreach (var i in p)
+ //{
+ // sb.Append($"\r\n参数:{i.ParameterName},参数值:{i.Value}");
+ //}
+ sb.Append($"\r\n 完整SQL:{UtilMethods.GetSqlString(DbType.MySql, s, p)}");
+ logger?.LogDebug(sb.ToString());
+ };
+ //扩展
+ this.OnSqlSugarClientConfig(db);
+ });
+ }
+
+ //上下文对象扩展
+ protected virtual void OnSqlSugarClientConfig(ISqlSugarClient sqlSugarClient)
+ {
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Uow/SqlsugarUnitOfWork.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Uow/SqlsugarUnitOfWork.cs
new file mode 100644
index 00000000..bda2bc4a
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Uow/SqlsugarUnitOfWork.cs
@@ -0,0 +1,59 @@
+using Microsoft.Extensions.DependencyInjection;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Model;
+using Yi.Framework.Ddd.Repositories;
+using Yi.Framework.Uow;
+
+namespace Yi.Framework.Core.Sqlsugar.Uow
+{
+ public class SqlsugarUnitOfWork : IUnitOfWork
+ {
+ public ISqlSugarClient Db { get; set; }
+ public ITenant Tenant { get; set; }
+ public bool IsTran { get; set; }
+ public bool IsCommit { get; set; }
+ public bool IsClose { get; set; }
+
+ public void Dispose()
+ {
+
+ if (this.IsTran && IsCommit == false)
+ {
+ this.Tenant.RollbackTran();
+ }
+ if (this.Db.Ado.Transaction == null && IsClose == false)
+ {
+ this.Db.Close();
+ }
+ }
+
+ public bool Commit()
+ {
+ if (this.IsTran && this.IsCommit == false)
+ {
+ this.Tenant.CommitTran();
+ IsCommit = true;
+ }
+ if (this.Db.Ado.Transaction == null && this.IsClose == false)
+ {
+ this.Db.Close();
+ IsClose = true;
+ }
+ return IsCommit;
+ }
+
+ public IRepository GetRepository()
+ {
+ if (ServiceLocatorModel.Instance is null)
+ throw new ArgumentNullException("ServiceLocatorModel.Instance");
+ //又是你这个骚东西
+ return ServiceLocatorModel.Instance.GetRequiredService>();
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Uow/SqlsugarUnitOfWorkManager.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Uow/SqlsugarUnitOfWorkManager.cs
new file mode 100644
index 00000000..17e35ae2
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Uow/SqlsugarUnitOfWorkManager.cs
@@ -0,0 +1,37 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Uow;
+
+namespace Yi.Framework.Core.Sqlsugar.Uow
+{
+ ///
+ /// 此部分为sqlsugr的魔改版本
+ ///
+ internal class SqlsugarUnitOfWorkManager : IUnitOfWorkManager
+ {
+ public SqlsugarUnitOfWorkManager(ISqlSugarClient db)
+ {
+ this.Db = db;
+ }
+ public ISqlSugarClient Db { get; set; }
+ public IUnitOfWork CreateContext(bool isTran = true)
+ {
+ SqlsugarUnitOfWork uow = new SqlsugarUnitOfWork();
+ return CreateContext(isTran, uow);
+ }
+ private IUnitOfWork CreateContext(bool isTran, SqlsugarUnitOfWork sugarUnitOf)
+ {
+ sugarUnitOf.Db = Db;
+ sugarUnitOf.Tenant = Db.AsTenant();
+ sugarUnitOf.IsTran = isTran;
+ Db.Open();
+ if (isTran)
+ Db.AsTenant().BeginTran();
+ return sugarUnitOf;
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Yi.Framework.Core.Sqlsugar.csproj b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Yi.Framework.Core.Sqlsugar.csproj
new file mode 100644
index 00000000..d7032fa3
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/Yi.Framework.Core.Sqlsugar.csproj
@@ -0,0 +1,24 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/YiFrameworkCoreSqlsugarModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/YiFrameworkCoreSqlsugarModule.cs
new file mode 100644
index 00000000..104082e7
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core.Sqlsugar/YiFrameworkCoreSqlsugarModule.cs
@@ -0,0 +1,37 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using StartupModules;
+using Yi.Framework.Core.Configuration;
+using Yi.Framework.Core.Sqlsugar.Extensions;
+using Yi.Framework.Core.Sqlsugar.Filters;
+using Yi.Framework.Core.Sqlsugar.Options;
+using Yi.Framework.Core.Sqlsugar.Repositories;
+using Yi.Framework.Core.Sqlsugar.Uow;
+using Yi.Framework.Data.Filters;
+using Yi.Framework.Ddd;
+using Yi.Framework.Ddd.Repositories;
+using Yi.Framework.Uow;
+
+namespace Yi.Framework.Core.Sqlsugar
+{
+ public class YiFrameworkCoreSqlsugarModule : IStartupModule
+ {
+ public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context)
+ {
+ app.UseSqlsugarCodeFirstServer();
+ }
+
+ public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context)
+ {
+ services.AddTransient(typeof(IRepository<>), typeof(SqlsugarRepository<>));
+ //services.Replace(new ServiceDescriptor(typeof(IUnitOfWorkManager), typeof(SqlsugarUnitOfWorkManager), ServiceLifetime.Singleton));
+ services.Replace(new ServiceDescriptor(typeof(IDataFilter), typeof(SqlsugarDataFilter), ServiceLifetime.Scoped));
+ services.Configure(Appsettings.appConfiguration("DbConnOptions"));
+
+ //使用db上下文
+ services.AddDbSqlsugarContextServer();
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/AppServiceAttribute.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/AppServiceAttribute.cs
new file mode 100644
index 00000000..59beb884
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/AppServiceAttribute.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Attributes
+{
+ /// 1、[AppService]:自动去找接口,如果存在就是接口,如果不存在就是本身
+ /// 2、[AppService(ServiceType = typeof(注册抽象或者接口或者本身))],手动去注册,放type即可
+ ///
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ public class AppServiceAttribute : Attribute
+ {
+ public AppServiceAttribute() { }
+ public AppServiceAttribute(Type? serviceType)
+ {
+ ServiceType=serviceType;
+ }
+
+ public AppServiceAttribute(Type? serviceType, LifeTime serviceLifetime)
+ {
+ ServiceType = serviceType;
+ ServiceLifetime= serviceLifetime;
+ }
+ ///
+ /// 服务声明周期
+ /// 不给默认值的话注册的是作用域
+ ///
+ public LifeTime ServiceLifetime { get; set; } = LifeTime.Transient;
+ ///
+ /// 指定服务类型
+ ///
+ public Type? ServiceType { get; set; }
+
+ }
+
+ public enum LifeTime
+ {
+ Transient, Scoped, Singleton
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/AutowiredAttribute.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/AutowiredAttribute.cs
new file mode 100644
index 00000000..d9c752af
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/AutowiredAttribute.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.Attributes
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public class AutowiredAttribute : Attribute
+ {
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/DependsOnAttribute.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/DependsOnAttribute.cs
new file mode 100644
index 00000000..085dbcc9
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/DependsOnAttribute.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Attributes
+{
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public class DependsOnAttribute : Attribute
+ {
+ public Type[] DependedTypes { get; }
+
+ public DependsOnAttribute(params Type[] dependedTypes)
+ {
+ DependedTypes = dependedTypes ?? new Type[0];
+ }
+
+ public virtual Type[] GetDependedTypes()
+ {
+ return DependedTypes;
+ }
+ }
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/QueryParameterAttribute.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/QueryParameterAttribute.cs
new file mode 100644
index 00000000..20c1740e
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Attributes/QueryParameterAttribute.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Enums;
+
+namespace Yi.Framework.Core.Attributes
+{
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)]
+ public class QueryParameterAttribute:Attribute
+ {
+ public QueryParameterAttribute()
+ {
+ }
+ public QueryParameterAttribute(QueryOperatorEnum queryOperatorEnum)
+ {
+ QueryOperator = queryOperatorEnum;
+ }
+
+ public QueryOperatorEnum QueryOperator { get; set; }
+
+ ///
+ /// 验证值为0时是否作为查询条件
+ /// true-作为查询条件 false-不作为查询条件
+ ///
+ public bool VerifyIsZero { get; set; } = false;
+
+ ///
+ ///
+ ///
+ public string ColumnName { get; set; }
+
+ public ColumnTypeEnum ColumnType { get; set; }
+ }
+
+ public enum ColumnTypeEnum
+ {
+ datetime,
+ @bool
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Configuration/Appsettings.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Configuration/Appsettings.cs
new file mode 100644
index 00000000..d121ee54
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Configuration/Appsettings.cs
@@ -0,0 +1,91 @@
+using Microsoft.Extensions.Configuration.Json;
+using Microsoft.Extensions.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Configuration
+{
+ public class Appsettings
+ {
+ static IConfiguration? Configuration { get; set; }
+ static string? contentPath { get; set; }
+
+ public Appsettings(string contentPath)
+ {
+ string Path = "appsettings.json";
+
+ //如果你把配置文件 是 根据环境变量来分开了,可以这样写
+ //Path = $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json";
+
+ Configuration = new ConfigurationBuilder()
+ .SetBasePath(contentPath)
+ .Add(new JsonConfigurationSource { Path = Path, Optional = false, ReloadOnChange = true })//这样的话,可以直接读目录里的json文件,而不是 bin 文件夹下的,所以不用修改复制属性
+ .Build();
+ }
+
+ public Appsettings(IConfiguration configuration)
+ {
+ Configuration = configuration;
+ }
+
+ ///
+ /// 封装要操作的字符
+ ///
+ /// 节点配置
+ ///
+ public static string? app(params string[] sections)
+ {
+ try
+ {
+
+ if (sections.Any())
+ {
+ return Configuration?[string.Join(":", sections)];
+ }
+ }
+ catch (Exception) { }
+
+ return "";
+ }
+
+ public static bool appBool(params string[] sections)
+ {
+
+ return Bool(app(sections));
+
+ }
+
+ public static bool Bool(object? thisValue)
+ {
+ bool reval = false;
+ if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out reval))
+ {
+ return reval;
+ }
+ return reval;
+ }
+
+ ///
+ /// 递归获取配置信息数组
+ ///
+ ///
+ ///
+ ///
+ public static T app(params string[] sections)
+ {
+ T app = Activator.CreateInstance();
+ // 引用 Microsoft.Extensions.Configuration.Binder 包
+ Configuration.Bind(string.Join(":", sections), app);
+ return app;
+ }
+
+
+ public static IConfiguration? appConfiguration(params string[] sections)
+ {
+ return Configuration?.GetSection(string.Join(":", sections));
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Const/PathConst.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Const/PathConst.cs
new file mode 100644
index 00000000..ba393ce5
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Const/PathConst.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Const
+{
+ ///
+ /// 定义公共文件常量
+ ///
+ public class PathConst
+ {
+ public const string wwwroot = "wwwroot";
+ public const string DataTemplate = "_DataTemplate";
+ public const string DataExport = "_DataExport";
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Const/TokenTypeConst.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Const/TokenTypeConst.cs
new file mode 100644
index 00000000..850293ac
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Const/TokenTypeConst.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Const
+{
+ public class TokenTypeConst
+ {
+ public const string Id = nameof(Id);
+
+ public const string UserName= nameof(UserName);
+
+ public const string TenantId = nameof(TenantId);
+
+ public const string Email = nameof(Email);
+
+ public const string PhoneNumber = nameof(PhoneNumber);
+
+ public const string Roles = nameof(Roles);
+
+ public const string Permission = nameof(Permission);
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/CurrentPrincipalAccessorBase.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/CurrentPrincipalAccessorBase.cs
new file mode 100644
index 00000000..06dd9632
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/CurrentPrincipalAccessorBase.cs
@@ -0,0 +1,32 @@
+using System.Security.Claims;
+using Yi.Framework.Core.Utils;
+
+namespace Yi.Framework.Core.CurrentUsers.Accessor
+{
+ public abstract class CurrentPrincipalAccessorBase : ICurrentPrincipalAccessor
+ {
+ public ClaimsPrincipal Principal => _currentPrincipal.Value ?? GetClaimsPrincipal();
+
+ private readonly AsyncLocal _currentPrincipal = new AsyncLocal();
+
+ protected abstract ClaimsPrincipal GetClaimsPrincipal();
+
+ public virtual IDisposable Change(ClaimsPrincipal principal)
+ {
+ return SetCurrent(principal);
+ }
+
+ private IDisposable SetCurrent(ClaimsPrincipal principal)
+ {
+ var parent = Principal;
+ _currentPrincipal.Value = principal;
+ return new DisposeAction, ClaimsPrincipal>>(static (state) =>
+ {
+ var (currentPrincipal, parent) = state;
+ currentPrincipal.Value = parent;
+ }, (_currentPrincipal, parent));
+
+ }
+ }
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/HttpContextCurrentPrincipalAccessor.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/HttpContextCurrentPrincipalAccessor.cs
new file mode 100644
index 00000000..e17de77e
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/HttpContextCurrentPrincipalAccessor.cs
@@ -0,0 +1,27 @@
+using Microsoft.AspNetCore.Http;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.CurrentUsers.Accessor;
+
+namespace Yi.Framework.Core.CurrentUsers.Accessor
+{
+ public class HttpContextCurrentPrincipalAccessor : ThreadCurrentPrincipalAccessor
+ {
+ private readonly IHttpContextAccessor _httpContextAccessor;
+
+ public HttpContextCurrentPrincipalAccessor(IHttpContextAccessor httpContextAccessor)
+ {
+ _httpContextAccessor = httpContextAccessor;
+ }
+
+ protected override ClaimsPrincipal GetClaimsPrincipal()
+ {
+ return _httpContextAccessor.HttpContext?.User ?? base.GetClaimsPrincipal();
+ }
+
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ICurrentPrincipalAccessor.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ICurrentPrincipalAccessor.cs
new file mode 100644
index 00000000..50dff9c4
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ICurrentPrincipalAccessor.cs
@@ -0,0 +1,11 @@
+using System.Security.Claims;
+
+namespace Yi.Framework.Core.CurrentUsers.Accessor
+{
+ public interface ICurrentPrincipalAccessor
+ {
+ ClaimsPrincipal Principal { get; }
+ IDisposable Change(ClaimsPrincipal principal);
+ }
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/StaticCurrentPrincipalAccessor.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/StaticCurrentPrincipalAccessor.cs
new file mode 100644
index 00000000..83c24746
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/StaticCurrentPrincipalAccessor.cs
@@ -0,0 +1,15 @@
+using System.Security.Claims;
+
+using Yi.Framework.Core.CurrentUsers.Accessor;
+
+namespace SF.CurrentUser.CS.Accessor
+{
+ public class StaticPrincipalAccessor : CurrentPrincipalAccessorBase
+ {
+ public static ClaimsPrincipal ClaimsPrincipal { get; set; }
+ protected override ClaimsPrincipal GetClaimsPrincipal()
+ {
+ return ClaimsPrincipal;
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ThreadCurrentPrincipalAccessor.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ThreadCurrentPrincipalAccessor.cs
new file mode 100644
index 00000000..f4138299
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ThreadCurrentPrincipalAccessor.cs
@@ -0,0 +1,13 @@
+using System.Security.Claims;
+
+namespace Yi.Framework.Core.CurrentUsers.Accessor
+{
+ public class ThreadCurrentPrincipalAccessor : CurrentPrincipalAccessorBase
+ {
+ protected override ClaimsPrincipal GetClaimsPrincipal()
+ {
+ return Thread.CurrentPrincipal as ClaimsPrincipal;
+ }
+ }
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/CurrentUser.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/CurrentUser.cs
new file mode 100644
index 00000000..051fcb3d
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/CurrentUser.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Const;
+using Yi.Framework.Core.CurrentUsers.Accessor;
+
+namespace Yi.Framework.Core.CurrentUsers
+{
+ public class CurrentUser : ICurrentUser
+ {
+ private readonly ICurrentPrincipalAccessor _principalAccessor;
+ public CurrentUser(ICurrentPrincipalAccessor principalAccessor)
+ {
+ _principalAccessor = principalAccessor;
+ }
+ public bool IsAuthenticated => Id != 0;
+
+ public long Id => FindUserId();
+
+ public string UserName => this.FindClaimValue(TokenTypeConst.UserName);
+
+ ///
+ /// 暂时为默认值
+ ///
+ public Guid TenantId { get; set; } = Guid.Empty;
+
+ public string Email => FindClaimValue(TokenTypeConst.Email);
+
+ public bool EmailVerified=> false;
+
+ public string PhoneNumber => FindClaimValue(TokenTypeConst.PhoneNumber);
+
+ public bool PhoneNumberVerified => false;
+
+ public string[]? Roles => this.FindClaims(TokenTypeConst.Roles).Select(c => c.Value).Distinct().ToArray();
+
+ public string[]? Permission => this.FindClaims(TokenTypeConst.Permission).Select(c => c.Value).Distinct().ToArray();
+
+ public virtual Claim FindClaim(string claimType)
+ {
+ return _principalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == claimType);
+ }
+
+ public virtual Claim[] FindClaims(string claimType)
+ {
+ return _principalAccessor.Principal?.Claims.Where(c => c.Type == claimType).ToArray() ?? new Claim[0];
+ }
+
+ public virtual Claim[] GetAllClaims()
+ {
+ return _principalAccessor.Principal?.Claims.ToArray() ?? new Claim[0];
+ }
+
+ public string FindClaimValue(string claimType)
+ {
+ return FindClaim(claimType)?.Value;
+ }
+
+
+ public long FindUserId()
+ {
+ var userIdOrNull = _principalAccessor.Principal?.Claims?.FirstOrDefault(c => c.Type == TokenTypeConst.Id);
+ if (userIdOrNull == null || string.IsNullOrWhiteSpace(userIdOrNull.Value))
+ {
+ return 0;
+ }
+
+ if (long.TryParse(userIdOrNull.Value, out long userId))
+ {
+ return userId;
+ }
+
+ return 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/ICurrentUser.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/ICurrentUser.cs
new file mode 100644
index 00000000..8364db9c
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/ICurrentUser.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.CurrentUsers
+{
+ public interface ICurrentUser
+ {
+ public bool IsAuthenticated { get; }
+ public long Id { get; }
+
+ public string UserName { get; }
+
+ public Guid TenantId { get; }
+
+ public string Email { get; }
+
+ public bool EmailVerified { get; }
+
+ public string PhoneNumber { get; }
+
+ public bool PhoneNumberVerified { get; }
+
+ public string[]? Roles { get; }
+
+ public string[]? Permission { get; }
+
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/DependencyInjection/IScopedDependency.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/DependencyInjection/IScopedDependency.cs
new file mode 100644
index 00000000..2b5f628c
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/DependencyInjection/ISingletonDependency.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/DependencyInjection/ISingletonDependency.cs
new file mode 100644
index 00000000..d79d686d
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/DependencyInjection/ITransientDependency.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/DependencyInjection/ITransientDependency.cs
new file mode 100644
index 00000000..b075939d
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/FileTypeEnum.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/FileTypeEnum.cs
new file mode 100644
index 00000000..1776d35f
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/FileTypeEnum.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Enums
+{
+ ///
+ /// 定义公共文件路径
+ ///
+ public enum FileTypeEnum
+ {
+ File,
+ Image,
+ Thumbnail,
+ Excel,
+ Temp
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/OrderByEnum.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/OrderByEnum.cs
new file mode 100644
index 00000000..b1edac3a
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/OrderByEnum.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Enums
+{
+ public enum OrderByEnum
+ {
+ Asc,
+ Desc
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/QueryOperatorEnum.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/QueryOperatorEnum.cs
new file mode 100644
index 00000000..13439675
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/QueryOperatorEnum.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Enums
+{
+ public enum QueryOperatorEnum
+ {
+ ///
+ /// 相等
+ ///
+ Equal,
+ ///
+ /// 匹配
+ ///
+ Like,
+ ///
+ /// 大于
+ ///
+ GreaterThan,
+ ///
+ /// 大于或等于
+ ///
+ GreaterThanOrEqual,
+ ///
+ /// 小于
+ ///
+ LessThan,
+ ///
+ /// 小于或等于
+ ///
+ LessThanOrEqual,
+ ///
+ /// 等于集合
+ ///
+ In,
+ ///
+ /// 不等于集合
+ ///
+ NotIn,
+ ///
+ /// 左边匹配
+ ///
+ LikeLeft,
+ ///
+ /// 右边匹配
+ ///
+ LikeRight,
+ ///
+ /// 不相等
+ ///
+ NoEqual,
+ ///
+ /// 为空或空
+ ///
+ IsNullOrEmpty,
+ ///
+ /// 不为空
+ ///
+ IsNot,
+ ///
+ /// 不匹配
+ ///
+ NoLike,
+ ///
+ /// 时间段 值用 "|" 隔开
+ ///
+ DateRange
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/ResultCodeEnum.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/ResultCodeEnum.cs
new file mode 100644
index 00000000..e4197867
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Enums/ResultCodeEnum.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Enums
+{
+ public enum ResultCodeEnum
+ {
+ ///
+ /// 操作成功。
+ ///
+ Success = 200,
+
+ ///
+ /// 操作不成功
+ ///
+ NotSuccess = 500,
+
+ ///
+ /// 无权限
+ ///
+ NoPermission = 401,
+
+ ///
+ /// 被拒绝
+ ///
+ Denied = 403
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/AuthException.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/AuthException.cs
new file mode 100644
index 00000000..154ea3c6
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/AuthException.cs
@@ -0,0 +1,53 @@
+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.Enums;
+
+namespace Yi.Framework.Core.Exceptions
+{
+ public class AuthException : Exception,
+ IHasErrorCode,
+ IHasErrorDetails,
+ IHasLogLevel
+ {
+ public int Code { get; set; }
+
+ public string? Details { get; set; }
+
+ public LogLevel LogLevel { get; set; }
+
+ public AuthException(
+
+ string? message = null,
+ ResultCodeEnum code = ResultCodeEnum.NoPermission,
+ string? details = null,
+ Exception? innerException = null,
+ LogLevel logLevel = LogLevel.Warning)
+ : base(message, innerException)
+ {
+ Code =(int) code;
+ Details = details;
+ LogLevel = logLevel;
+ }
+
+ ///
+ /// 序列化参数的构造函数
+ ///
+ public AuthException(SerializationInfo serializationInfo, StreamingContext context)
+ : base(serializationInfo, context)
+ {
+
+ }
+
+ public AuthException WithData(string name, object value)
+ {
+ Data[name] = value;
+ return this;
+ }
+
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/BusinessException.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/BusinessException.cs
new file mode 100644
index 00000000..64a8d54f
--- /dev/null
+++ b/Yi.Framework.Net6/src/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.Enums;
+
+namespace Yi.Framework.Core.Exceptions
+{
+ public class BusinessException : Exception,
+ IHasErrorCode,
+ IHasErrorDetails,
+ IHasLogLevel
+ {
+ public int Code { get; set; }
+
+ public string? Details { get; set; }
+
+ public LogLevel LogLevel { get; set; }
+
+ public BusinessException(
+ int code = (int)ResultCodeEnum.Denied,
+ 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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/ExceptionExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/ExceptionExtensions.cs
new file mode 100644
index 00000000..1a9e5b59
--- /dev/null
+++ b/Yi.Framework.Net6/src/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.Enums;
+
+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 int GetLogErrorCode(this Exception exception, ResultCodeEnum defaultCode = ResultCodeEnum.NotSuccess)
+ {
+ return (exception as IHasErrorCode)?.Code ?? (int)defaultCode;
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/IHasErrorCode.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/IHasErrorCode.cs
new file mode 100644
index 00000000..d57e891b
--- /dev/null
+++ b/Yi.Framework.Net6/src/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.Enums;
+
+namespace Yi.Framework.Core.Exceptions
+{
+ internal interface IHasErrorCode
+ {
+ int Code { get; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/IHasErrorDetails.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/IHasErrorDetails.cs
new file mode 100644
index 00000000..2ea6e71f
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/IHasLogLevel.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/IHasLogLevel.cs
new file mode 100644
index 00000000..038eaa32
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/UserFriendlyException.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/UserFriendlyException.cs
new file mode 100644
index 00000000..97a71782
--- /dev/null
+++ b/Yi.Framework.Net6/src/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.Enums;
+
+namespace Yi.Framework.Core.Exceptions
+{
+ public class UserFriendlyException : BusinessException
+ {
+ public UserFriendlyException(
+string message,
+int code = (int)ResultCodeEnum.Denied,
+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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Extensions/AutoIocAddExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Extensions/AutoIocAddExtensions.cs
new file mode 100644
index 00000000..e66b870f
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Extensions/AutoIocAddExtensions.cs
@@ -0,0 +1,132 @@
+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.Attributes;
+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 = Yi.Framework.Core.Module.ModuleAssembly.Assemblies;
+ 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 serviceAttributes = type.GetCustomAttributes();
+ if (serviceAttributes is null)
+ {
+ return;
+ }
+ //处理多个特性注入情况
+ foreach (var serviceAttribute in serviceAttributes)
+ {
+
+ if (serviceAttribute is not null)
+ {
+ //泛型类需要单独进行处理
+ //情况1:使用自定义[AppService(ServiceType = typeof(注册抽象或者接口))],手动去注册,放type即可
+ var serviceType = serviceAttribute.ServiceType;
+ //if (serviceType is not null && serviceType.Name.Contains("IDataSeed`"))
+ //{
+ // Console.WriteLine();
+ //}
+
+ //情况2 自动去找接口,如果存在就是接口,如果不存在就是本身
+ if (serviceType == null)
+ {
+ //获取最远靠近的接口
+ var p = type.GetInterfaces().ToList();
+ var firstInter = type.GetInterfaces().Where(u => u.Name == $"I{type.Name}").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().Where(u => u != typeof(ITransientDependency) && u.Name == $"I{type.Name}").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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Extensions/ModuleExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Extensions/ModuleExtensions.cs
new file mode 100644
index 00000000..8dc1db62
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Extensions/ModuleExtensions.cs
@@ -0,0 +1,36 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using StartupModules.Internal;
+using StartupModules;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Module;
+
+namespace Yi.Framework.Core.Extensions
+{
+
+ ///
+ /// 该类来自于StartupModules
+ ///
+ public static class ModuleExtensions
+ {
+ public static WebApplicationBuilder UseYiModules(this WebApplicationBuilder builder, Type startType)
+ {
+ var moduleManager = new ModuleManager(startType);
+
+
+ Assembly[] assemblies2 = moduleManager.ToAssemblyArray(moduleManager.Invoker());
+ return builder.UseStartupModules(delegate (StartupModulesOptions options)
+ {
+ options.DiscoverStartupModules(assemblies2);
+ });
+ }
+ }
+}
+
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/AssemblyHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/AssemblyHelper.cs
new file mode 100644
index 00000000..7f646689
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/AssemblyHelper.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Helper
+{
+ public static class AssemblyHelper
+ {
+
+ ///
+ /// 此处统一获取程序集,排除微软内部相关
+ ///
+ ///
+ public static Assembly[] GetAllLoadAssembly()
+ {
+ return AppDomain.CurrentDomain.GetAssemblies();
+ }
+
+ public static List GetReferanceAssemblies(this AppDomain domain)
+ {
+ var list = new List();
+ domain.GetAssemblies().ToList().ForEach(i =>
+ {
+ GetReferanceAssemblies(i, list);
+ });
+ return list;
+ }
+ private static void GetReferanceAssemblies(Assembly assembly, List list)
+ {
+ assembly.GetReferencedAssemblies().ToList().ForEach(i =>
+ {
+ var ass = Assembly.Load(i);
+ if (!list.Contains(ass))
+ {
+ list.Add(ass);
+ GetReferanceAssemblies(ass, list);
+ }
+ });
+ }
+
+ public static List GetClass(string assemblyFile, string? className = null, string? spaceName = null)
+ {
+ Assembly assembly = Assembly.Load(assemblyFile);
+ return assembly.GetTypes().Where(m => m.IsClass
+ && className == null ? true : m.Name == className
+ && spaceName == null ? true : m.Namespace == spaceName
+ && !m.Name.StartsWith("<>")
+ ).ToList();
+ }
+
+ public static List GetClassByParentClass(string assemblyFile, Type type)
+ {
+ Assembly assembly = Assembly.Load(assemblyFile);
+
+ List resList = new List();
+
+ List typeList = assembly.GetTypes().Where(m => m.IsClass).ToList();
+ foreach (var t in typeList)
+ {
+ var data = t.BaseType;
+ if (data == type)
+ {
+ resList.Add(t);
+ }
+
+ }
+ return resList;
+ }
+
+
+ public static List GetClassByInterfaces(string assemblyFile, Type type)
+ {
+ Assembly assembly = Assembly.Load(assemblyFile);
+
+ List resList = new List();
+
+ List typeList = assembly.GetTypes().Where(m => m.IsClass).ToList();
+ foreach (var t in typeList)
+ {
+ var data = t.GetInterfaces();
+ if (data.Contains(type))
+ {
+ resList.Add(t);
+ }
+
+ }
+ return resList;
+ }
+
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/Base32Helper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/Base32Helper.cs
new file mode 100644
index 00000000..2f89bc1c
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/ConsoleHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/ConsoleHelper.cs
new file mode 100644
index 00000000..dfd6a8ab
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/DateHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/DateHelper.cs
new file mode 100644
index 00000000..0ac37315
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/DistinctHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/DistinctHelper.cs
new file mode 100644
index 00000000..18df6efb
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/EnumHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/EnumHelper.cs
new file mode 100644
index 00000000..eaef0d79
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/EnumHelper.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Helper
+{
+ public static class EnumHelper
+ {
+ public static New EnumToEnum(this object oldEnum)
+ {
+ if (oldEnum is null)
+ {
+ throw new ArgumentNullException(nameof(oldEnum));
+ }
+ return (New)Enum.ToObject(typeof(New), oldEnum.GetHashCode());
+ }
+
+ public static TEnum StringToEnum(this string str)
+ {
+ return (TEnum)Enum.Parse(typeof(TEnum), str);
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/ExpressionHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/ExpressionHelper.cs
new file mode 100644
index 00000000..bac80dc0
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/ExpressionHelper.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Helper
+{
+ public static class ExpressionHelper
+ {
+
+
+ ///
+ /// Expression表达式树lambda参数拼接组合
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Expression Compose(this Expression first, Expression second, Func merge)
+ {
+ var parameterMap = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
+ var secondBody = LambdaParameteRebinder.ReplaceParameter(parameterMap, second.Body);
+ return Expression.Lambda(merge(first.Body, secondBody), first.Parameters);
+ }
+
+ ///
+ /// Expression表达式树lambda参数拼接--false
+ ///
+ ///
+ ///
+ public static Expression> False() => f => false;
+
+ ///
+ /// Expression表达式树lambda参数拼接-true
+ ///
+ ///
+ ///
+ public static Expression> True() => f => true;
+
+ ///
+ /// Expression表达式树lambda参数拼接--and
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Expression> And(this Expression> first, Expression> second) => first.Compose(second, Expression.And);
+
+ ///
+ /// Expression表达式树lambda参数拼接--or
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Expression> Or(this Expression> first, Expression> second) => first.Compose(second, Expression.Or);
+ }
+
+ public class LambdaParameteRebinder : ExpressionVisitor
+ {
+ ///
+ /// 存放表达式树的参数的字典
+ ///
+ private readonly Dictionary map;
+
+ ///
+ /// 构造函数
+ ///
+ ///
+ public LambdaParameteRebinder(Dictionary map)
+ {
+ this.map = map ?? new Dictionary();
+ }
+
+ ///
+ /// 重载参数访问的方法,访问表达式树参数,如果字典中包含,则取出
+ ///
+ /// 表达式树参数
+ ///
+ protected override Expression VisitParameter(ParameterExpression node)
+ {
+ if (map.TryGetValue(node, out ParameterExpression expression))
+ {
+ node = expression;
+ }
+ return base.VisitParameter(node);
+ }
+
+ public static Expression ReplaceParameter(Dictionary map, Expression exp)
+ {
+ return new LambdaParameteRebinder(map).Visit(exp);
+ }
+ }
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/FileHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/FileHelper.cs
new file mode 100644
index 00000000..906b7253
--- /dev/null
+++ b/Yi.Framework.Net6/src/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.Core.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, 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, 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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/HtmlHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/HtmlHelper.cs
new file mode 100644
index 00000000..857de345
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/HttpHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/HttpHelper.cs
new file mode 100644
index 00000000..eb37c1ae
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/IdHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/IdHelper.cs
new file mode 100644
index 00000000..ca1ad53d
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/IpHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/IpHelper.cs
new file mode 100644
index 00000000..60a4fdd7
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/JsonHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/JsonHelper.cs
new file mode 100644
index 00000000..87e29171
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/JsonHelper.cs
@@ -0,0 +1,518 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+
+namespace Yi.Framework.Core.Helper
+{
+ public class JsonHelper
+ {
+ public static string ObjToStr(T obj, string dateTimeFormat)
+ {
+ IsoDateTimeConverter timeConverter = new IsoDateTimeConverter()
+ {
+ DateTimeFormat = dateTimeFormat
+ };
+ return Newtonsoft.Json.JsonConvert.SerializeObject(obj, Formatting.Indented, timeConverter);
+ }
+
+ 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
+ {
+ System.Text.Json.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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/MD5Hepler.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/MD5Hepler.cs
new file mode 100644
index 00000000..c7f4c1f2
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/MimeHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/MimeHelper.cs
new file mode 100644
index 00000000..d238f27e
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/MimeHelper.cs
@@ -0,0 +1,260 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Enums;
+
+namespace Yi.Framework.Core.Helper
+{
+ public static class MimeHelper
+ {
+ // 通过自己定义一个静态类
+ // 将所有的Content Type都扔进去吧
+ // 调用的时候直接调用静态方法即可。
+
+ public static List ImageType { get; set; } = new List
+ {
+ ".jpg",".png",".jpge"
+ };
+
+ 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;
+ }
+
+ public static FileTypeEnum GetFileType(string fileName)
+ {
+ var extension = Path.GetExtension(fileName);
+ if(ImageType.Contains(extension.ToLower()))
+ return FileTypeEnum.Image;
+ return FileTypeEnum.File;
+
+
+ }
+
+ 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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/RSAFileHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/RSAFileHelper.cs
new file mode 100644
index 00000000..cc873a2c
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/RSAHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/RSAHelper.cs
new file mode 100644
index 00000000..f2fd6990
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/RandomHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/RandomHelper.cs
new file mode 100644
index 00000000..2a5ba81f
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/ReflexHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/ReflexHelper.cs
new file mode 100644
index 00000000..33316b1d
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/ReflexHelper.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Helper
+{
+ public static class ReflexHelper
+ {
+
+ #region 对象相关
+ ///
+ /// 取对象属性值
+ ///
+ ///
+ ///
+ ///
+ public static string GetModelValue(string FieldName, object obj)
+ {
+ try
+ {
+ Type Ts = obj.GetType();
+ object o = Ts.GetProperty(FieldName).GetValue(obj, null);
+ if (null == o)
+ return null;
+ string Value = Convert.ToString(o);
+ if (string.IsNullOrEmpty(Value))
+ return null;
+ return Value;
+ }
+ catch (Exception ex)
+ {
+ throw ex;
+ }
+ return null;
+ }
+
+
+ ///
+ /// 设置对象属性值
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool SetModelValue(string FieldName, object Value, object obj)
+ {
+ try
+ {
+ Type Ts = obj.GetType();
+ Ts.GetProperty(FieldName).SetValue(obj, Value, null);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ throw ex;
+ }
+ return false;
+ }
+ #endregion
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/SnowflakeHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/SnowflakeHelper.cs
new file mode 100644
index 00000000..cefe21e6
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/SnowflakeHelper.cs
@@ -0,0 +1,102 @@
+using SqlSugar;
+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 NextId { get => SnowFlakeSingle.Instance.NextId(); }
+
+ 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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/StringHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/StringHelper.cs
new file mode 100644
index 00000000..faa28a5f
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/TreeHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/TreeHelper.cs
new file mode 100644
index 00000000..bd688170
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/UnicodeHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/UnicodeHelper.cs
new file mode 100644
index 00000000..0d8e737f
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/UrlHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/UrlHelper.cs
new file mode 100644
index 00000000..ed073407
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/XmlHelper.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Helper/XmlHelper.cs
new file mode 100644
index 00000000..f40dd811
--- /dev/null
+++ b/Yi.Framework.Net6/src/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/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Model/GobalLogModel.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Model/GobalLogModel.cs
new file mode 100644
index 00000000..b93b8a76
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Model/GobalLogModel.cs
@@ -0,0 +1,9 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Model
+{
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Model/ServiceLocatorModel.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Model/ServiceLocatorModel.cs
new file mode 100644
index 00000000..297b7e6d
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Model/ServiceLocatorModel.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Model
+{
+ public static class ServiceLocatorModel
+ {
+ public static IServiceProvider Instance { get; set; }
+ }
+}
+
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Module/ModuleAssembly.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Module/ModuleAssembly.cs
new file mode 100644
index 00000000..080564d2
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Module/ModuleAssembly.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Module
+{
+ public class ModuleAssembly
+ {
+ private static HashSet assemblies=new HashSet();
+ public static Assembly[] Assemblies { get=> assemblies.ToArray();}
+
+ public static void Add(Assembly assembly)
+ {
+ assemblies.Add(assembly);
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Module/ModuleManager.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Module/ModuleManager.cs
new file mode 100644
index 00000000..22e4b15e
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Module/ModuleManager.cs
@@ -0,0 +1,119 @@
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Attributes;
+
+namespace Yi.Framework.Core.Module
+{
+
+ internal class ModuleManager
+ {
+ ///
+ /// 全部程序集
+ ///
+ private List ResultType = new List();
+
+ ///
+ /// 开始程序集
+ ///
+ private Type StartType;
+ public ModuleManager(Type startType)
+ {
+ StartType = startType;
+ }
+
+ ///
+ /// 执行
+ ///
+ ///
+ public List Invoker()
+ {
+ StartBFSNodes(StartType);
+ ResultType= ResultType.Distinct().ToList();
+ var result = StartTopologicalSortNodes().Reverse().ToList();
+
+ Logger? _logger = LogManager.Setup().LoadConfigurationFromAssemblyResource(typeof(ModuleManager).Assembly).GetCurrentClassLogger();
+ foreach (var r in result)
+ {
+ //添加全局模块程序集
+ ModuleAssembly.Add(r.Assembly);
+ _logger.Info($"意框架正在加载模块:{r.Name}");
+ }
+ return result;
+ }
+
+
+ private Type[] StartTopologicalSortNodes()
+ {
+ List> topologicalSortNodes = new List>();
+
+
+ //添加注册到节点
+ foreach (var res in ResultType)
+ {
+ var typeNode = new TopologicalSortNode(res);
+ topologicalSortNodes.Add(typeNode);
+ }
+
+ Dictionary> nodeDic = topologicalSortNodes.ToDictionary(x => x.Data);
+
+
+ //各个节点互相添加依赖
+ foreach (var node in topologicalSortNodes)
+ {
+ GetDependsOnType(node.Data)?.ToList().ForEach(x => node.AddDependent(nodeDic[x]));
+ }
+
+
+
+ return TopologicalSortNode.TopologicalSort(topologicalSortNodes).Select(x => x.Data).ToArray();
+ }
+
+ ///
+ /// BFS获取全部程序集
+ ///
+ ///
+ private void StartBFSNodes(Type node)
+ {
+ ResultType.Add(node);
+ var nodes = GetDependsOnType(node);
+ if (nodes is not null && nodes.Count() != 0)
+ {
+ foreach (var n in nodes)
+ {
+ StartBFSNodes(n);
+ }
+ }
+ }
+
+
+ ///
+ /// 获取模块 需依赖的模块
+ ///
+ ///
+ ///
+ private Type[]? GetDependsOnType(Type type)
+ {
+ var dependsOnbuild = type.GetCustomAttributes(typeof(DependsOnAttribute), false).FirstOrDefault() as DependsOnAttribute;
+ if (dependsOnbuild is null)
+ {
+ return new Type[0];
+ }
+ return dependsOnbuild.GetDependedTypes();
+ }
+
+
+ public List ToAssemblyList()
+ {
+ return ResultType.Select(a => a.Assembly).ToList();
+ }
+ public Assembly[] ToAssemblyArray(List types)
+ {
+ return types.Select(a => a.Assembly).ToArray();
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Module/TopologicalSortNode.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Module/TopologicalSortNode.cs
new file mode 100644
index 00000000..630e0382
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Module/TopologicalSortNode.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Core.Module
+{
+ public class TopologicalSortNode
+ {
+ public T Data { get; private set; }
+ public List> Dependents { get; private set; }
+ public int IncomingEdges { get; private set; }
+ public TopologicalSortNode(T data)
+ {
+ Data = data;
+ Dependents = new List>();
+ IncomingEdges = 0;
+ }
+ public void AddDependent(TopologicalSortNode dependent)
+ {
+ Dependents.Add(dependent);
+ dependent.IncomingEdges++;
+ }
+
+
+ public static List> TopologicalSort(List> graph)
+ {
+ List> result = new List>();
+ Queue> queue = new Queue>();
+ // 将所有入度为 0 的节点加入队列
+ foreach (TopologicalSortNode node in graph)
+ {
+ if (node.IncomingEdges == 0)
+ {
+ queue.Enqueue(node);
+ }
+ }
+ // 依次将入度为 0 的节点出队,并将它的依赖节点的入度减 1
+ while (queue.Count > 0)
+ {
+ TopologicalSortNode node = queue.Dequeue();
+ result.Add(node);
+ foreach (TopologicalSortNode dependent in node.Dependents)
+ {
+ dependent.IncomingEdges--;
+ if (dependent.IncomingEdges == 0)
+ {
+ queue.Enqueue(dependent);
+ }
+ }
+ }
+ // 如果存在入度不为 0 的节点,则说明图中存在环
+ foreach (TopologicalSortNode node in graph)
+ {
+ if (node.IncomingEdges != 0)
+ {
+ throw new ArgumentException("模块之间存在互相依赖!");
+ }
+ }
+ return result;
+ }
+
+
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Utils/DisposeAction.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Utils/DisposeAction.cs
new file mode 100644
index 00000000..e1cff0ac
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Utils/DisposeAction.cs
@@ -0,0 +1,27 @@
+using System.Diagnostics.CodeAnalysis;
+
+namespace Yi.Framework.Core.Utils
+{
+ public class DisposeAction : IDisposable
+ {
+ private readonly Action _action;
+
+ private readonly T _parameter;
+
+ ///
+ /// Creates a new object.
+ ///
+ /// Action to be executed when this object is disposed.
+ /// The parameter of the action.
+ public DisposeAction(Action action, T parameter)
+ {
+ _action = action;
+ _parameter = parameter;
+ }
+
+ public void Dispose()
+ {
+ _action(_parameter);
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Yi.Framework.Core.csproj b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Yi.Framework.Core.csproj
new file mode 100644
index 00000000..b83ece5f
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Yi.Framework.Core.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/YiFrameworkCoreModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/YiFrameworkCoreModule.cs
new file mode 100644
index 00000000..34425609
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/YiFrameworkCoreModule.cs
@@ -0,0 +1,40 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using NLog.Extensions.Logging;
+using StartupModules;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Core.Configuration;
+using Yi.Framework.Core.CurrentUsers;
+using Yi.Framework.Core.Extensions;
+using Yi.Framework.Core.Model;
+
+namespace Yi.Framework.Core
+{
+ public class YiFrameworkCoreModule : IStartupModule
+ {
+ public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context)
+ {
+ //服务定位实例赋值
+ ServiceLocatorModel.Instance = app.ApplicationServices;
+
+ //全局错误,需要靠前,放在此处无效
+ //app.UseErrorHandlingServer();
+
+
+ }
+
+ public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context)
+ {
+ //添加全局配置类
+ services.AddSingleton(new Appsettings(context.Configuration));
+ //全盘扫描,自动依赖注入
+ services.AddAutoIocServer();
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/AuditedObject.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/AuditedObject.cs
new file mode 100644
index 00000000..9867b612
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/AuditedObject.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Auditing
+{
+ public class AuditedObject : IAuditedObject
+ {
+ public DateTime CreationTime { get; set; }= DateTime.Now;
+
+ public long? CreatorId { get; set; }
+
+ public long? LastModifierId { get; set; }
+
+ public DateTime? LastModificationTime { get; set; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IAuditedObject.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IAuditedObject.cs
new file mode 100644
index 00000000..68a63853
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IAuditedObject.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Auditing
+{
+ public interface IAuditedObject : ICreationAuditedObject, IModificationAuditedObject
+ {
+ }
+
+ public interface IAuditedObject : IAuditedObject, ICreationAuditedObject, IModificationAuditedObject
+ {
+
+ }
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/ICreationAuditedObject.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/ICreationAuditedObject.cs
new file mode 100644
index 00000000..e136c6e4
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/ICreationAuditedObject.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Auditing
+{
+ public interface ICreationAuditedObject : IHasCreationTime, IMayHaveCreator
+ {
+
+ }
+
+ public interface ICreationAuditedObject : ICreationAuditedObject, IMayHaveCreator
+ {
+
+ }
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IDeletionAuditedObject.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IDeletionAuditedObject.cs
new file mode 100644
index 00000000..34d536e0
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IDeletionAuditedObject.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Auditing
+{
+ public interface IDeletionAuditedObject : IHasDeletionTime
+ {
+ long? DeleterId { get; }
+ }
+
+ public interface IDeletionAuditedObject : IDeletionAuditedObject
+ {
+
+ TUser Deleter { get; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IFullAuditedObject.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IFullAuditedObject.cs
new file mode 100644
index 00000000..cc081c7d
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IFullAuditedObject.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Auditing
+{
+ public interface IFullAuditedObject : IAuditedObject, IDeletionAuditedObject
+ {
+
+ }
+
+ public interface IFullAuditedObject : IAuditedObject, IFullAuditedObject, IDeletionAuditedObject
+ {
+
+ }
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasCreationTime.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasCreationTime.cs
new file mode 100644
index 00000000..6291376e
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasCreationTime.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Yi.Framework.Data.Auditing;
+
+
+public interface IHasCreationTime
+{
+
+ DateTime CreationTime { get; set; }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasDeletionTime.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasDeletionTime.cs
new file mode 100644
index 00000000..5888993d
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasDeletionTime.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Data.Entities;
+
+namespace Yi.Framework.Data.Auditing
+{
+ public interface IHasDeletionTime : ISoftDelete
+ {
+ DateTime? DeletionTime { get; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasEntityVersion.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasEntityVersion.cs
new file mode 100644
index 00000000..c35b983a
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasEntityVersion.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Auditing
+{
+ public interface IHasEntityVersion
+ {
+ int EntityVersion { get; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasModificationTime.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasModificationTime.cs
new file mode 100644
index 00000000..a61cbae7
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IHasModificationTime.cs
@@ -0,0 +1,9 @@
+
+namespace Yi.Framework.Data.Auditing;
+
+
+public interface IHasModificationTime
+{
+
+ DateTime? LastModificationTime { get; }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IMayHaveCreator.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IMayHaveCreator.cs
new file mode 100644
index 00000000..c5ee3eef
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IMayHaveCreator.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Yi.Framework.Data.Auditing;
+
+public interface IMayHaveCreator
+{
+ TCreator Creator { get; }
+}
+
+public interface IMayHaveCreator
+{
+ long? CreatorId { get; }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IModificationAuditedObject.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IModificationAuditedObject.cs
new file mode 100644
index 00000000..c70a2631
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IModificationAuditedObject.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Auditing
+{
+ public interface IModificationAuditedObject : IHasModificationTime
+ {
+ long? LastModifierId { get; }
+ }
+
+ public interface IModificationAuditedObject : IModificationAuditedObject
+ {
+ TUser LastModifier { get; }
+ }
+
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IMustHaveCreator.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IMustHaveCreator.cs
new file mode 100644
index 00000000..c2b316c7
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Auditing/IMustHaveCreator.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Yi.Framework.Data.Auditing;
+
+public interface IMustHaveCreator : IMustHaveCreator
+{
+ TCreator Creator { get; }
+}
+
+public interface IMustHaveCreator
+{
+ long CreatorId { get; }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/DataSeeds/AbstractDataSeed.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/DataSeeds/AbstractDataSeed.cs
new file mode 100644
index 00000000..ab046d33
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/DataSeeds/AbstractDataSeed.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Yi.Framework.Ddd.Repositories;
+
+namespace Yi.Framework.Data.DataSeeds
+{
+ public abstract class AbstractDataSeed : IDataSeed
+ {
+ protected readonly IRepository _repository;
+ public AbstractDataSeed(IRepository repository)
+ {
+ _repository = repository;
+ }
+
+ ///
+ /// 简单种子数据,重写该方法即可
+ ///
+ ///
+ public abstract List GetSeedData();
+
+
+ ///
+ /// 复杂数据,重写该方法即可
+ ///
+ ///
+ public async virtual Task DataHandlerAsync()
+ {
+ return await _repository.InsertRangeAsync(GetSeedData());
+ }
+
+ ///
+ /// 这个用来处理判断是否数据库还存在数据
+ ///
+ ///
+ public virtual async Task IsInvoker()
+ {
+ var p = await _repository.IsAnyAsync(x=>true);
+ var p2 = await _repository.CountAsync(x => true);
+ if (await _repository.CountAsync(u => true) > 0)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ ///
+ /// 完全自定义数据,处理该方法即可
+ ///
+ ///
+ public async virtual Task InvokerAsync()
+ {
+ bool res = true;
+ if (await IsInvoker())
+ {
+ return await DataHandlerAsync();
+ }
+ return res;
+ }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/DataSeeds/IDataSeed.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/DataSeeds/IDataSeed.cs
new file mode 100644
index 00000000..22dc95ff
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/DataSeeds/IDataSeed.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.DataSeeds
+{
+ public interface IDataSeed
+ {
+ Task InvokerAsync();
+ }
+
+ public interface IDataSeed: IDataSeed
+ {
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/IMultiTenant.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/IMultiTenant.cs
new file mode 100644
index 00000000..e8bc3266
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/IMultiTenant.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Entities
+{
+ public interface IMultiTenant
+ {
+ public Guid TenantId { get; set; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/IOrderNum.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/IOrderNum.cs
new file mode 100644
index 00000000..04ab97c4
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/IOrderNum.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Entities
+{
+ public interface IOrderNum
+ {
+ int OrderNum { get; set; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/ISoftDelete.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/ISoftDelete.cs
new file mode 100644
index 00000000..cbbc5277
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/ISoftDelete.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Entities
+{
+ public interface ISoftDelete
+ {
+ public bool IsDeleted { get; set; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/IState.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/IState.cs
new file mode 100644
index 00000000..fee2f365
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Entities/IState.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yi.Framework.Data.Entities
+{
+ public interface IState
+ {
+ public bool State { get; set; }
+ }
+}
diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Extensions/DataFiterExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Extensions/DataFiterExtensions.cs
new file mode 100644
index 00000000..ba4a8788
--- /dev/null
+++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Extensions/DataFiterExtensions.cs
@@ -0,0 +1,41 @@
+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.Data.Entities;
+using Yi.Framework.Data.Filters;
+
+namespace Yi.Framework.Data.Extensions
+{
+ public static class DataFilterExtensions
+ {
+ public static IApplicationBuilder UseDataFiterServer(this IApplicationBuilder builder)
+ {
+ return builder.UseMiddleware();
+ }
+ }
+
+ public class DataFilterMiddleware
+ {
+ private readonly RequestDelegate _next;
+ private readonly ILogger _logger;
+ public DataFilterMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
+ {
+ this._next = next;
+ this._logger = loggerFactory.CreateLogger();
+ }
+ public async Task InvokeAsync(HttpContext context, IDataFilter dataFilter)
+ {
+ //添加默认的过滤器
+ dataFilter.AddFilter