diff --git a/README.md b/README.md index fe5bd056..e712a6cc 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ [![.NET](https://github.com/nsnail/NetAdmin/actions/workflows/nightly-build.yml/badge.svg)](https://github.com/nsnail/NetAdmin/actions/workflows/nightly-build.yml) [![MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/nsnail/NetAdmin/blob/main/LICENSE) -[![Furion](https://img.shields.io/badge/Furion-4.x-blueviolet.svg)](https://github.com/nsnail/NetAdmin/blob/main/LICENSE) [![FreeSql](https://img.shields.io/badge/FreeSql-3.x-orange.svg)](https://github.com/nsnail/NetAdmin/blob/main/LICENSE) ## 在线预览 @@ -86,7 +85,6 @@ XC-->XA | 语言 | 集成领域 | 开源库 | |------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | C# | Web基础框架 | [ASP.NET Core](https://github.com/dotnet/aspnetcore) | -| C# | 快速开发脚手架 | [Furion](https://gitee.com/dotnetchina/Furion) | | C# | 数据库关系映射 | [FreeSql](https://github.com/dotnetcore/FreeSql) | | C# | 代码质量检查 | [Roslynator.Analyzers](https://github.com/josefpihrt/roslynator) \| [SonarAnalyzer.CSharp](https://github.com/SonarSource/sonar-dotnet) \| [StyleCop.Analyzers](https://github.com/DotNetAnalyzers/StyleCopAnalyzers) | | C# | 单元测试框架 | [xunit](https://github.com/xunit/xunit) \| [coverlet.collector](https://github.com/coverlet-coverage/coverlet) | diff --git a/assets/seed-data/Sys_Job.json b/assets/seed-data/Sys_Job.json index c9ef928f..6458c34c 100644 --- a/assets/seed-data/Sys_Job.json +++ b/assets/seed-data/Sys_Job.json @@ -4,7 +4,7 @@ "ExecutionCron": "0 * * * * ?", "HttpMethod": 3, "JobName": "HTTP 请求测试", - "NextExecTime": "2020/9/13 12:26:40", + "NextExecTime": "2020-09-13 12:26:40", "NextTimeId": 1600000000, "RequestUrl": "https://httpbin.org/ip", "Status": 1, diff --git a/src/backend/NetAdmin.AdmServer.Host/Startup.cs b/src/backend/NetAdmin.AdmServer.Host/Startup.cs index f9186b2f..46c0ad27 100644 --- a/src/backend/NetAdmin.AdmServer.Host/Startup.cs +++ b/src/backend/NetAdmin.AdmServer.Host/Startup.cs @@ -63,7 +63,7 @@ namespace NetAdmin.AdmServer.Host .UseVueAdmin() // 托管管理后台,仅在非调试模式下 .UsePrometheus() // 使用Prometheus中间件,启用HTTP性能监控 #endif - .UseInject(string.Empty) // 使用Inject中间件,Furion脚手架的依赖注入支持 + .UseInject(string.Empty) // 使用Inject中间件,Gurion脚手架的依赖注入支持 .UseUnifyResultStatusCodes() // 使用UnifyResultStatusCodes中间件,用于统一处理结果状态码 .UseCorsAccessor() // 使用CorsAccessor中间件,启用跨域资源共享(CORS)支持 .UseRouting() // 使用Routing中间件,配置路由映射 diff --git a/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Development.json b/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Development.json index 6fc2bc4b..1ea59e5b 100644 --- a/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Development.json +++ b/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Development.json @@ -1,5 +1,4 @@ { - "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", "Logging": { "LogLevel": { "Default": "Debug", diff --git a/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Remote.json b/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Remote.json index 6fc2bc4b..1ea59e5b 100644 --- a/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Remote.json +++ b/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Remote.json @@ -1,5 +1,4 @@ { - "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", "Logging": { "LogLevel": { "Default": "Debug", diff --git a/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Test.json b/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Test.json index 6fc2bc4b..1ea59e5b 100644 --- a/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Test.json +++ b/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.Test.json @@ -1,5 +1,4 @@ { - "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", "Logging": { "LogLevel": { "Default": "Debug", diff --git a/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.json b/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.json index a4bd517e..cac780d7 100644 --- a/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.json +++ b/src/backend/NetAdmin.AdmServer.Infrastructure/AdmSettings.json @@ -1,5 +1,4 @@ { - "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", // Swagger文档配置 ------------------------------------------------------------------------------ "SpecificationDocumentSettings": { "GroupOpenApiInfos": [ diff --git a/src/backend/NetAdmin.Application/Services/RepositoryService.cs b/src/backend/NetAdmin.Application/Services/RepositoryService.cs index 83da1922..7209bc07 100644 --- a/src/backend/NetAdmin.Application/Services/RepositoryService.cs +++ b/src/backend/NetAdmin.Application/Services/RepositoryService.cs @@ -100,8 +100,8 @@ public abstract class RepositoryService(BasicReposit TEntity newValue // , IEnumerable includeFields // , string[] excludeFields = null // - , Expression> whereExp = null // - , string whereSql = null // + , Expression> whereExp = null // + , string whereSql = null // , bool ignoreVersion = false) { // 默认匹配主键 diff --git a/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj b/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj index b5f971ee..0667e5a9 100644 --- a/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj +++ b/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj @@ -10,7 +10,6 @@ - diff --git a/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Development.json b/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Development.json index b5cc14fa..838e24e0 100644 --- a/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Development.json +++ b/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Development.json @@ -1,5 +1,4 @@ { - "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", "AppSettings": { "InjectSpecificationDocument": true, "InjectMiniProfiler": true diff --git a/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Remote.json b/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Remote.json index b5cc14fa..838e24e0 100644 --- a/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Remote.json +++ b/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Remote.json @@ -1,5 +1,4 @@ { - "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", "AppSettings": { "InjectSpecificationDocument": true, "InjectMiniProfiler": true diff --git a/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Test.json b/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Test.json index b5cc14fa..838e24e0 100644 --- a/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Test.json +++ b/src/backend/NetAdmin.Infrastructure/NetAdminSettings.Test.json @@ -1,5 +1,4 @@ { - "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", "AppSettings": { "InjectSpecificationDocument": true, "InjectMiniProfiler": true diff --git a/src/backend/NetAdmin.Infrastructure/NetAdminSettings.json b/src/backend/NetAdmin.Infrastructure/NetAdminSettings.json index 9a1d2e84..2fac885b 100644 --- a/src/backend/NetAdmin.Infrastructure/NetAdminSettings.json +++ b/src/backend/NetAdmin.Infrastructure/NetAdminSettings.json @@ -1,5 +1,4 @@ { - "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", // App基本配置 "AppSettings": { "InjectSpecificationDocument": false, diff --git a/src/backend/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs b/src/backend/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs index 470a92b3..cb86ee6f 100644 --- a/src/backend/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs +++ b/src/backend/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs @@ -1,7 +1,6 @@ #if DBTYPE_SQLSERVER using Microsoft.Data.SqlClient; #endif -using Newtonsoft.Json; using DataType = FreeSql.DataType; namespace NetAdmin.Infrastructure.Utils; @@ -103,10 +102,18 @@ public sealed class FreeSqlBuilder(DatabaseOptions databaseOptions) continue; } - var fileContent = File.ReadAllText(file); + using var fs = File.OpenRead(file); + var jsonSerializerOptions = new JsonSerializerOptions(JsonSerializerOptions.Default) // + { + AllowTrailingCommas = true + , ReadCommentHandling = JsonCommentHandling.Skip + , TypeInfoResolver + = new DefaultJsonTypeInfoResolver { Modifiers = { JsonIgnoreRemover.RemoveJsonIgnore(entityType) } } + }; + _ = jsonSerializerOptions.Converters.AddDateTimeTypeConverters(); - dynamic entities = JsonConvert.DeserializeObject( // - fileContent, typeof(IEnumerable<>).MakeGenericType(entityType)); + var jsonTypeInfo = JsonTypeInfo.CreateJsonTypeInfo(typeof(IEnumerable<>).MakeGenericType(entityType), jsonSerializerOptions); + var entities = JsonSerializer.Deserialize(fs, jsonTypeInfo); // 如果表存在数据,跳过 var select = typeof(IFreeSql).GetMethod(nameof(freeSql.Select), 1, Type.EmptyTypes)?.MakeGenericMethod(entityType).Invoke(freeSql, null); diff --git a/src/backend/NetAdmin.Infrastructure/Utils/JsonIgnoreRemover.cs b/src/backend/NetAdmin.Infrastructure/Utils/JsonIgnoreRemover.cs new file mode 100644 index 00000000..dc682860 --- /dev/null +++ b/src/backend/NetAdmin.Infrastructure/Utils/JsonIgnoreRemover.cs @@ -0,0 +1,98 @@ +namespace NetAdmin.Infrastructure.Utils; + +/// +/// 忽略 JsonIgnore 特性 +/// +public static class JsonIgnoreRemover +{ + private delegate TValue RefFunc(ref TObject arg); + + /// + /// 忽略 JsonIgnore 特性 + /// + public static Action RemoveJsonIgnore(Type type) + { + return typeInfo => { + if (!type.IsAssignableFrom(typeInfo.Type) || typeInfo.Kind != JsonTypeInfoKind.Object) { + return; + } + + foreach (var property in typeInfo.Properties.Where(property => property.ShouldSerialize != null && + property.AttributeProvider?.IsDefined(typeof(JsonIgnoreAttribute), true) == + true)) { + property.Get ??= CreatePropertyGetter(property); + property.Set ??= CreatePropertySetter(property); + if (property.Get != null) { + property.ShouldSerialize = null; + } + } + }; + } + + private static Func CreateGetter(Type type, MethodInfo method) + { + if (method == null) { + return null; + } + + #pragma warning disable S3011 + var myMethod = typeof(JsonIgnoreRemover).GetMethod(nameof(CreateGetterGeneric), BindingFlags.NonPublic | BindingFlags.Static)!; + #pragma warning restore S3011 + return (Func)myMethod.MakeGenericMethod(type, method.ReturnType).Invoke(null, [method])!; + } + + private static Func CreateGetterGeneric(MethodInfo method) + { + ArgumentNullException.ThrowIfNull(method); + + if (typeof(TObject).IsValueType) { + var func = (RefFunc)Delegate.CreateDelegate(typeof(RefFunc), null, method); + return o => { + var tObj = (TObject)o; + return func(ref tObj); + }; + } + else { + var func = (Func)Delegate.CreateDelegate(typeof(Func), method); + return o => func((TObject)o); + } + } + + private static Func CreatePropertyGetter(JsonPropertyInfo property) + { + return property.AttributeProvider as PropertyInfo is { ReflectedType: not null } info && info.GetGetMethod() is { } getMethod + ? CreateGetter(info.ReflectedType, getMethod) + : null; + } + + private static Action CreatePropertySetter(JsonPropertyInfo property) + { + return property.AttributeProvider as PropertyInfo is { ReflectedType: not null } info && info.GetSetMethod() is { } setMethod + ? CreateSetter(info.ReflectedType, setMethod) + : null; + } + + private static Action CreateSetter(Type type, MethodInfo method) + { + if (method == null) { + return null; + } + + #pragma warning disable S3011 + var myMethod = typeof(JsonIgnoreRemover).GetMethod(nameof(CreateSetterGeneric), BindingFlags.NonPublic | BindingFlags.Static)!; + #pragma warning restore S3011 + return (Action)myMethod.MakeGenericMethod(type, method.GetParameters().Single().ParameterType).Invoke(null, [method])!; + } + + private static Action CreateSetterGeneric(MethodInfo method) + { + ArgumentNullException.ThrowIfNull(method); + + if (typeof(TObject).IsValueType) { + return (o, v) => method.Invoke(o, [v]); + } + + var func = (Action)Delegate.CreateDelegate(typeof(Action), method); + return (o, v) => func((TObject)o, (TValue)v); + } +} \ No newline at end of file