diff --git a/src/Yi.Framework/Yi.Framework.Application/Class1.cs b/src/Yi.Framework/Yi.Framework.Application/Class1.cs deleted file mode 100644 index 4d36f3a8..00000000 --- a/src/Yi.Framework/Yi.Framework.Application/Class1.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Yi.Framework.Application -{ - public class Class1 - { - - } -} \ No newline at end of file diff --git a/src/Yi.Framework/Yi.Framework.Application/SwaggerDoc.xml b/src/Yi.Framework/Yi.Framework.Application/SwaggerDoc.xml new file mode 100644 index 00000000..63b3b0e5 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Application/SwaggerDoc.xml @@ -0,0 +1,8 @@ + + + + Yi.Framework.Application + + + + diff --git a/src/Yi.Framework/Yi.Framework.Application/TestService.cs b/src/Yi.Framework/Yi.Framework.Application/TestService.cs new file mode 100644 index 00000000..1314d27a --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Application/TestService.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Mvc; +using Panda.DynamicWebApi; +using Panda.DynamicWebApi.Attributes; + +namespace Yi.Framework.Application +{ + [DynamicWebApi] + public class TestService : IDynamicWebApi + { + public string GetShijie() + { + return "你好世界"; + } + } +} \ No newline at end of file diff --git a/src/Yi.Framework/Yi.Framework.Application/Yi.Framework.Application.csproj b/src/Yi.Framework/Yi.Framework.Application/Yi.Framework.Application.csproj index 132c02c5..99fcd661 100644 --- a/src/Yi.Framework/Yi.Framework.Application/Yi.Framework.Application.csproj +++ b/src/Yi.Framework/Yi.Framework.Application/Yi.Framework.Application.csproj @@ -1,9 +1,21 @@ - + net6.0 enable enable + True + ./SwaggerDoc.xml + + + + + + + Always + + + diff --git a/src/Yi.Framework/Yi.Framework.Application/YiFrameworkApplicationModule.cs b/src/Yi.Framework/Yi.Framework.Application/YiFrameworkApplicationModule.cs new file mode 100644 index 00000000..3f328608 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Application/YiFrameworkApplicationModule.cs @@ -0,0 +1,24 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using StartupModules; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Application +{ + public class YiFrameworkApplicationModule : IStartupModule + { + public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context) + { + + } + + public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) + { + + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.AspNetCore/Class1.cs b/src/Yi.Framework/Yi.Framework.AspNetCore/Class1.cs deleted file mode 100644 index db18c875..00000000 --- a/src/Yi.Framework/Yi.Framework.AspNetCore/Class1.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Yi.Framework.AspNetCore -{ - public class Class1 - { - - } -} \ No newline at end of file diff --git a/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/CorsUseExtensions.cs b/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/CorsUseExtensions.cs new file mode 100644 index 00000000..7a7e3078 --- /dev/null +++ b/src/Yi.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 UseCorsService(this IApplicationBuilder app) + { + app.UseCors("CorsPolicy"); + } + + } +} diff --git a/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/SwaggerUseExtensons.cs b/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/SwaggerUseExtensons.cs new file mode 100644 index 00000000..293100d9 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/SwaggerUseExtensons.cs @@ -0,0 +1,49 @@ +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 url, string name) + { + this.url = url; + this.name = name; + } + public string url { get; set; } + public string name { get; set; } + } +} diff --git a/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/AutoIocAddExtensions.cs b/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/AutoIocAddExtensions.cs new file mode 100644 index 00000000..6ac5f84a --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/AutoIocAddExtensions.cs @@ -0,0 +1,64 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.Attribute; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class AutoIocAddExtensions + { + public static IServiceCollection AddAutoIocServer(this IServiceCollection services, params string[] assemblyStr) + { + foreach (var a in assemblyStr) + { + RegIoc(services, Assembly.Load(a)); + } + return services; + } + private static void RegIoc(IServiceCollection services, Assembly assembly) + { + foreach (var type in assembly.GetTypes()) + { + + var serviceAttribute = type.GetCustomAttribute(); + if (serviceAttribute is not null) + { + //情况1:使用自定义[AppService(ServiceType = typeof(注册抽象或者接口))],手动去注册,放type即可 + var serviceType = serviceAttribute.ServiceType; + //情况2 自动去找接口,如果存在就是接口,如果不存在就是本身 + if (serviceType == null) + { + //获取最靠近的接口 + var firstInter = type.GetInterfaces().FirstOrDefault(); + if (firstInter is null) + { + serviceType = type; + } + else + { + serviceType = firstInter; + } + } + + switch (serviceAttribute.ServiceLifetime) + { + case LifeTime.Singleton: + services.AddSingleton(serviceType, type); + break; + case LifeTime.Scoped: + services.AddScoped(serviceType, type); + break; + case LifeTime.Transient: + services.AddTransient(serviceType, type); + break; + } + + } + } + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CorsAddExtensions.cs b/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CorsAddExtensions.cs new file mode 100644 index 00000000..56daefe6 --- /dev/null +++ b/src/Yi.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/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/SwaggerAddExtensions.cs b/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/SwaggerAddExtensions.cs new file mode 100644 index 00000000..fe322ea5 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/SwaggerAddExtensions.cs @@ -0,0 +1,74 @@ +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); + + //添加注释服务 + //为 Swagger JSON and UI设置xml文档注释路径 + //获取应用程序所在目录(绝对路径,不受工作目录影响,建议采用此方法获取路径使用windwos&Linux) + var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location); + if (basePath is null) + { + throw new Exception("未找到swagger文件"); + } + var apiXmlPath = Path.Combine(basePath, @"SwaggerDoc.xml");//控制器层注释 + //var entityXmlPath = Path.Combine(basePath, @"SwaggerDoc.xml");//实体注释 + //c.IncludeXmlComments(apiXmlPath, true);//true表示显示控制器注释 + //c.IncludeXmlComments(apiXmlPath, true); + + //这里路径应该动态获取,先暂时写死 + //c.IncludeXmlComments("E:\\Yi\\src\\Yi.Framework\\Yi.Framework.Application\\SwaggerDoc.xml", true); + + + //添加控制器注释 + //c.DocumentFilter(); + + //添加header验证信息 + //c.OperationFilter(); + //var security = new Dictionary> { { "Bearer", new string[] { } }, }; + 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/src/Yi.Framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj b/src/Yi.Framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj index 132c02c5..7aece253 100644 --- a/src/Yi.Framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj +++ b/src/Yi.Framework/Yi.Framework.AspNetCore/Yi.Framework.AspNetCore.csproj @@ -6,4 +6,14 @@ enable + + + + + + + + + + diff --git a/src/Yi.Framework/Yi.Framework.Autofac/Class1.cs b/src/Yi.Framework/Yi.Framework.Autofac/Class1.cs deleted file mode 100644 index 83fbc217..00000000 --- a/src/Yi.Framework/Yi.Framework.Autofac/Class1.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Yi.Framework.Autofac -{ - public class Class1 - { - - } -} \ No newline at end of file diff --git a/src/Yi.Framework/Yi.Framework.Autofac/Extensions/AutoFacExtensions.cs b/src/Yi.Framework/Yi.Framework.Autofac/Extensions/AutoFacExtensions.cs new file mode 100644 index 00000000..258314c1 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Autofac/Extensions/AutoFacExtensions.cs @@ -0,0 +1,22 @@ +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.Autofac.Extensions +{ + public static class AutoFacExtensions + { + public static IHostBuilder UseAutoFacServerProviderFactory(this IHostBuilder hostBuilder) + { + hostBuilder.UseServiceProviderFactory(new AutofacServiceProviderFactory()); + + return hostBuilder; + } + + } +} diff --git a/src/Yi.Framework/Yi.Framework.Autofac/Yi.Framework.Autofac.csproj b/src/Yi.Framework/Yi.Framework.Autofac/Yi.Framework.Autofac.csproj index 132c02c5..b8c46913 100644 --- a/src/Yi.Framework/Yi.Framework.Autofac/Yi.Framework.Autofac.csproj +++ b/src/Yi.Framework/Yi.Framework.Autofac/Yi.Framework.Autofac.csproj @@ -6,4 +6,13 @@ enable + + + + + + + + + diff --git a/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Class1.cs b/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Class1.cs deleted file mode 100644 index aba7f49f..00000000 --- a/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Class1.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Yi.Framework.Core.Sqlsugar -{ - public class Class1 - { - - } -} \ No newline at end of file diff --git a/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarExtensions.cs b/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarExtensions.cs new file mode 100644 index 00000000..c56ceb8c --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Extensions/SqlsugarExtensions.cs @@ -0,0 +1,136 @@ +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 DbType = SqlSugar.DbType; + +namespace Yi.Framework.Core.Sqlsugar.Extensions +{ + public static class SqlsugarExtensions + { + public static void AddSqlsugarServer(this IServiceCollection services, Action? action = null) + { + DbType dbType; + var slavaConFig = new List(); + if (Appsettings.appBool("MutiDB_Enabled")) + { + var readCon = Appsettings.app>("DbConn", "ReadUrl"); + + readCon.ForEach(s => + { + //如果是动态saas分库,这里的连接串都不能写死,需要动态添加,这里只配置共享库的连接 + slavaConFig.Add(new SlaveConnectionConfig() { ConnectionString = s }); + }); + } + + switch (Appsettings.app("DbSelect")) + { + case "Mysql": dbType = DbType.MySql; break; + case "Sqlite": dbType = DbType.Sqlite; break; + case "Sqlserver": dbType = DbType.SqlServer; break; + case "Oracle": dbType = DbType.Oracle; break; + default: throw new Exception("DbSelect配置写的TM是个什么东西?"); + } + SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig() + { + //准备添加分表分库 + DbType = dbType, + ConnectionString = Appsettings.app("DbConn", "WriteUrl"), + IsAutoCloseConnection = true, + MoreSettings = new ConnMoreSettings() + { + DisableNvarchar = true + }, + SlaveConnectionConfigs = slavaConFig, + //设置codefirst非空值判断 + ConfigureExternalServices = new ConfigureExternalServices + { + EntityService = (c, p) => + { + //// int? decimal?这种 isnullable=true + //if (c.PropertyType.IsGenericType && + //c.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) + //{ + // p.IsNullable = true; + //} + + //高版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) => + { + //var httpcontext = ServiceLocator.Instance.GetService().HttpContext; + switch (entityInfo.OperationType) + { + case DataFilterType.InsertByObject: + if (entityInfo.PropertyName == "CreateUser") + { + //entityInfo.SetValue(new Guid(httpcontext.Request.Headers["Id"].ToString())); + } + if (entityInfo.PropertyName == "TenantId") + { + //entityInfo.SetValue(new Guid(httpcontext.Request.Headers["TenantId"].ToString())); + } + if (entityInfo.PropertyName == "CreateTime") + { + entityInfo.SetValue(DateTime.Now); + } + break; + case DataFilterType.UpdateByObject: + if (entityInfo.PropertyName == "ModifyTime") + { + entityInfo.SetValue(DateTime.Now); + } + if (entityInfo.PropertyName == "ModifyUser") + { + //entityInfo.SetValue(new Guid(httpcontext.Request.Headers["Id"].ToString())); + } + break; + } + + }; + db.Aop.OnLogExecuting = (s, p) => + { + if (GobalLogModel.SqlLogEnable) + { + 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?.LogInformation(sb.ToString()); + } + + + }; + + }); + services.AddSingleton(sqlSugar);//这边是SqlSugarScope用AddSingleton + } + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Repository/SqlsugarRepository.cs b/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Repository/SqlsugarRepository.cs new file mode 100644 index 00000000..00ff1997 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Repository/SqlsugarRepository.cs @@ -0,0 +1,23 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.Attribute; +using Yi.Framework.Ddd.Repository; + +namespace Yi.Framework.Core.Sqlsugar.Repository +{ + [AppService] + public class SqlsugarRepository : SimpleClient, IRepository where T : class, new() + { + public SqlsugarRepository(ISqlSugarClient context) : base(context) + { + } + protected ISugarQueryable _DbQueryable { get { return base.Context.Queryable(); } set { } } + + protected ISqlSugarClient _Db { get { return base.Context; } set { } } + + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Yi.Framework.Core.Sqlsugar.csproj b/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Yi.Framework.Core.Sqlsugar.csproj index 132c02c5..e5d3cce8 100644 --- a/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Yi.Framework.Core.Sqlsugar.csproj +++ b/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/Yi.Framework.Core.Sqlsugar.csproj @@ -6,4 +6,13 @@ enable + + + + + + + + + diff --git a/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/YiFrameworkCoreSqlsugarModule.cs b/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/YiFrameworkCoreSqlsugarModule.cs new file mode 100644 index 00000000..1e4d47f0 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core.Sqlsugar/YiFrameworkCoreSqlsugarModule.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using StartupModules; +using Yi.Framework.Core.Sqlsugar.Extensions; +using Yi.Framework.Core.Sqlsugar.Repository; +using Yi.Framework.Ddd; +using Yi.Framework.Ddd.Repository; + +namespace Yi.Framework.Core.Sqlsugar +{ + public class YiFrameworkCoreSqlsugarModule : IStartupModule + { + public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context) + { + } + + public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) + { + services.AddTransient(typeof(IRepository<>), typeof(SqlsugarRepository<>)); + services.AddSqlsugarServer(); + } + } +} \ No newline at end of file diff --git a/src/Yi.Framework/Yi.Framework.Core/Attribute/AppServiceAttribute.cs b/src/Yi.Framework/Yi.Framework.Core/Attribute/AppServiceAttribute.cs new file mode 100644 index 00000000..af68ec48 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Attribute/AppServiceAttribute.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.Attribute +{ + /// 1、[AppService]:自动去找接口,如果存在就是接口,如果不存在就是本身 + /// 2、[AppService(ServiceType = typeof(注册抽象或者接口或者本身))],手动去注册,放type即可 + /// + [AttributeUsage(AttributeTargets.Class, Inherited = false)] + public class AppServiceAttribute : System.Attribute + { + /// + /// 服务声明周期 + /// 不给默认值的话注册的是作用域 + /// + public LifeTime ServiceLifetime { get; set; } = LifeTime.Scoped; + /// + /// 指定服务类型 + /// + public Type? ServiceType { get; set; } + + } + + public enum LifeTime + { + Transient, Scoped, Singleton + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Configuration/Appsettings.cs b/src/Yi.Framework/Yi.Framework.Core/Configuration/Appsettings.cs new file mode 100644 index 00000000..d121ee54 --- /dev/null +++ b/src/Yi.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/src/Yi.Framework/Yi.Framework.Core/Model/GobalLogModel.cs b/src/Yi.Framework/Yi.Framework.Core/Model/GobalLogModel.cs new file mode 100644 index 00000000..2474e386 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Core/Model/GobalLogModel.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.Model +{ + public class GobalLogModel + { + public static bool SqlLogEnable { get; set; } = true; + + public static bool LoginCodeEnable { get; set; } = true; + } +} diff --git a/src/Yi.Framework/Yi.Framework.Core/Model/ServiceLocatorModel.cs b/src/Yi.Framework/Yi.Framework.Core/Model/ServiceLocatorModel.cs new file mode 100644 index 00000000..a3663574 --- /dev/null +++ b/src/Yi.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/src/Yi.Framework/Yi.Framework.Core/Module/IYiModule.cs b/src/Yi.Framework/Yi.Framework.Core/Module/IYiModule.cs deleted file mode 100644 index db854bd9..00000000 --- a/src/Yi.Framework/Yi.Framework.Core/Module/IYiModule.cs +++ /dev/null @@ -1,13 +0,0 @@ -using StartupModules; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Yi.Framework.Core.Module -{ - public interface IYiModule: IStartupModule - { - } -} diff --git a/src/Yi.Framework/Yi.Framework.Core/Yi.Framework.Core.csproj b/src/Yi.Framework/Yi.Framework.Core/Yi.Framework.Core.csproj index d52f995e..53c43437 100644 --- a/src/Yi.Framework/Yi.Framework.Core/Yi.Framework.Core.csproj +++ b/src/Yi.Framework/Yi.Framework.Core/Yi.Framework.Core.csproj @@ -8,9 +8,11 @@ + + diff --git a/src/Yi.Framework/Yi.Framework.Core/YiFrameworkCoreModule.cs b/src/Yi.Framework/Yi.Framework.Core/YiFrameworkCoreModule.cs index 0c4cedad..a85f6c3e 100644 --- a/src/Yi.Framework/Yi.Framework.Core/YiFrameworkCoreModule.cs +++ b/src/Yi.Framework/Yi.Framework.Core/YiFrameworkCoreModule.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using StartupModules; using System; @@ -6,20 +7,27 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using Yi.Framework.Core.Module; +using Yi.Framework.Core.Configuration; +using Yi.Framework.Core.Model; namespace Yi.Framework.Core { - public class YiFrameworkCoreModule : IYiModule + public class YiFrameworkCoreModule : IStartupModule { public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context) { - throw new NotImplementedException(); + //服务定位实例赋值 + ServiceLocatorModel.Instance = app.ApplicationServices; } public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) { - throw new NotImplementedException(); + //添加全局配置类 + services.AddSingleton(new Appsettings(context.Configuration)); + + //全局日志 + GobalLogModel.SqlLogEnable = Appsettings.appBool("SqlLog_Enable"); + GobalLogModel.LoginCodeEnable = Appsettings.appBool("LoginCode_Enable"); } } } diff --git a/src/Yi.Framework/Yi.Framework.Ddd.Application/Repository/IRepository.cs b/src/Yi.Framework/Yi.Framework.Ddd.Application/Repository/IRepository.cs new file mode 100644 index 00000000..a42ad872 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Ddd.Application/Repository/IRepository.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Ddd.Repository +{ + public interface IRepository + { + Task GetByIdAsync(dynamic id); + } +} diff --git a/src/Yi.Framework/Yi.Framework.Ddd.Application/Yi.Framework.Ddd.csproj b/src/Yi.Framework/Yi.Framework.Ddd.Application/Yi.Framework.Ddd.csproj index 132c02c5..e7101d08 100644 --- a/src/Yi.Framework/Yi.Framework.Ddd.Application/Yi.Framework.Ddd.csproj +++ b/src/Yi.Framework/Yi.Framework.Ddd.Application/Yi.Framework.Ddd.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/src/Yi.Framework/Yi.Framework.Ddd.Application/YiFrameworkModule.cs b/src/Yi.Framework/Yi.Framework.Ddd.Application/YiFrameworkDddModule.cs similarity index 76% rename from src/Yi.Framework/Yi.Framework.Ddd.Application/YiFrameworkModule.cs rename to src/Yi.Framework/Yi.Framework.Ddd.Application/YiFrameworkDddModule.cs index 692d6460..68681aca 100644 --- a/src/Yi.Framework/Yi.Framework.Ddd.Application/YiFrameworkModule.cs +++ b/src/Yi.Framework/Yi.Framework.Ddd.Application/YiFrameworkDddModule.cs @@ -9,16 +9,14 @@ using System.Threading.Tasks; namespace Yi.Framework.Ddd { - public class YiFrameworkModule : IStartupModule + public class YiFrameworkDddModule:IStartupModule { public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context) { - throw new NotImplementedException(); } public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) { - throw new NotImplementedException(); } } } diff --git a/src/Yi.Framework/Yi.Framework.Web/Program.cs b/src/Yi.Framework/Yi.Framework.Web/Program.cs index 08dfb798..c7c4edab 100644 --- a/src/Yi.Framework/Yi.Framework.Web/Program.cs +++ b/src/Yi.Framework/Yi.Framework.Web/Program.cs @@ -1,28 +1,45 @@ +using AspNetCore.Microsoft.AspNetCore.Builder; +using Panda.DynamicWebApi; +using Yi.Framework.Application; +using Yi.Framework.Core; using Yi.Framework.Core.Extensions; +using Yi.Framework.Core.Sqlsugar; +using Yi.Framework.Core.Sqlsugar.Repository; +using Yi.Framework.Ddd; +using Yi.Framework.Ddd.Repository; +using Yi.Framework.Web; var builder = WebApplication.CreateBuilder(args); -builder.UseYiModules(); -// Add services to the container. +builder.UseYiModules( + typeof(YiFrameworkCoreModule).Assembly, + typeof(YiFrameworkDddModule).Assembly, + typeof(YiFrameworkCoreSqlsugarModule).Assembly + ); builder.Services.AddControllers(); -// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddDynamicWebApi(); + + builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddSwaggerGen(); + +builder.Services.AddSwaggerServer(); +//builder.Services.AddAutoIocServer("Yi.Framework.Core.Sqlsugar"); + var app = builder.Build(); -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) +app.Services.GetRequiredService>(); +//if (app.Environment.IsDevelopment()) { - app.UseSwagger(); - app.UseSwaggerUI(); + app.UseSwaggerServer(); } app.UseHttpsRedirection(); app.UseAuthorization(); +app.UseRouting(); app.MapControllers(); app.Run(); diff --git a/src/Yi.Framework/Yi.Framework.Web/TestEntity.cs b/src/Yi.Framework/Yi.Framework.Web/TestEntity.cs new file mode 100644 index 00000000..4a8735b3 --- /dev/null +++ b/src/Yi.Framework/Yi.Framework.Web/TestEntity.cs @@ -0,0 +1,6 @@ +namespace Yi.Framework.Web +{ + public class TestEntity + { + } +} diff --git a/src/Yi.Framework/Yi.Framework.Web/Yi.Framework.Web.csproj b/src/Yi.Framework/Yi.Framework.Web/Yi.Framework.Web.csproj index f7fead81..5023d2fe 100644 --- a/src/Yi.Framework/Yi.Framework.Web/Yi.Framework.Web.csproj +++ b/src/Yi.Framework/Yi.Framework.Web/Yi.Framework.Web.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -7,10 +7,9 @@ - - - - + + + diff --git a/src/Yi.Framework/Yi.Framework.Web/YiFrameworkWebModule.cs b/src/Yi.Framework/Yi.Framework.Web/YiFrameworkWebModule.cs index 2fe31c5d..cb0a1a58 100644 --- a/src/Yi.Framework/Yi.Framework.Web/YiFrameworkWebModule.cs +++ b/src/Yi.Framework/Yi.Framework.Web/YiFrameworkWebModule.cs @@ -1,9 +1,8 @@ using StartupModules; -using Yi.Framework.Core.Module; namespace Yi.Framework.Web { - public class YiFrameworkWebModule : IYiModule + public class YiFrameworkWebModule : IStartupModule { public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) { diff --git a/src/Yi.Framework/Yi.Framework.Web/appsettings.json b/src/Yi.Framework/Yi.Framework.Web/appsettings.json index 10f68b8c..504143d5 100644 --- a/src/Yi.Framework/Yi.Framework.Web/appsettings.json +++ b/src/Yi.Framework/Yi.Framework.Web/appsettings.json @@ -5,5 +5,20 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + + + //数据库列表 + "DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle" ], + //数据库类型选择 + "DbSelect": "Sqlite", + //数据库连接地址,支持读写分离 + "DbConn": { + "WriteUrl": "DataSource=yi-sqlsugar-dev.db", + "ReadUrl": [ + "DataSource=[xxxx]", //sqlite + "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //mysql + "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //sqlserver + ] + } } diff --git a/src/apiDemo/apiDemo.sln b/src/apiDemo/apiDemo.sln new file mode 100644 index 00000000..13c397c0 --- /dev/null +++ b/src/apiDemo/apiDemo.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33103.184 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "apiDemo", "apiDemo\apiDemo.csproj", "{F283397C-2CD9-412B-A561-5BE263D8088A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F283397C-2CD9-412B-A561-5BE263D8088A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F283397C-2CD9-412B-A561-5BE263D8088A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F283397C-2CD9-412B-A561-5BE263D8088A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F283397C-2CD9-412B-A561-5BE263D8088A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {32430753-D4CB-4090-8ADF-E4C6FEC4824A} + EndGlobalSection +EndGlobal diff --git a/src/apiDemo/apiDemo/Program.cs b/src/apiDemo/apiDemo/Program.cs new file mode 100644 index 00000000..fc642ce1 --- /dev/null +++ b/src/apiDemo/apiDemo/Program.cs @@ -0,0 +1,34 @@ +using Panda.DynamicWebApi; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(options => +{ + + +options.DocInclusionPredicate((docName, description) => true); + +options.IncludeXmlComments(@".\swagger.xml"); +}); +builder.Services.AddDynamicWebApi(); +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/src/apiDemo/apiDemo/Properties/launchSettings.json b/src/apiDemo/apiDemo/Properties/launchSettings.json new file mode 100644 index 00000000..2bfa75d5 --- /dev/null +++ b/src/apiDemo/apiDemo/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:39272", + "sslPort": 44328 + } + }, + "profiles": { + "apiDemo": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7262;http://localhost:5013", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/apiDemo/apiDemo/WeatherForecast.cs b/src/apiDemo/apiDemo/WeatherForecast.cs new file mode 100644 index 00000000..71e18825 --- /dev/null +++ b/src/apiDemo/apiDemo/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace apiDemo +{ + public class WeatherForecast + { + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} \ No newline at end of file diff --git a/src/apiDemo/apiDemo/WeatherForecastController.cs b/src/apiDemo/apiDemo/WeatherForecastController.cs new file mode 100644 index 00000000..55751f85 --- /dev/null +++ b/src/apiDemo/apiDemo/WeatherForecastController.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Mvc; +using Panda.DynamicWebApi; +using Panda.DynamicWebApi.Attributes; + +namespace apiDemo +{ + [DynamicWebApi] + [Route("[controller]")] + public class WeatherForecastController : IDynamicWebApi + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} \ No newline at end of file diff --git a/src/apiDemo/apiDemo/apiDemo.csproj b/src/apiDemo/apiDemo/apiDemo.csproj new file mode 100644 index 00000000..aabecdce --- /dev/null +++ b/src/apiDemo/apiDemo/apiDemo.csproj @@ -0,0 +1,16 @@ + + + + net6.0 + enable + enable + True + .\swagger.xml + + + + + + + + diff --git a/src/apiDemo/apiDemo/appsettings.json b/src/apiDemo/apiDemo/appsettings.json new file mode 100644 index 00000000..10f68b8c --- /dev/null +++ b/src/apiDemo/apiDemo/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/src/apiDemo/apiDemo/swagger.xml b/src/apiDemo/apiDemo/swagger.xml new file mode 100644 index 00000000..bfc3dac5 --- /dev/null +++ b/src/apiDemo/apiDemo/swagger.xml @@ -0,0 +1,8 @@ + + + + apiDemo + + + +