diff --git a/src/WMS.Web.Repositories/Configuration/DbContextExtensions.cs b/src/WMS.Web.Repositories/Configuration/DbContextExtensions.cs new file mode 100644 index 00000000..7ad4440e --- /dev/null +++ b/src/WMS.Web.Repositories/Configuration/DbContextExtensions.cs @@ -0,0 +1,225 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace WMS.Web.Repositories.Configuration +{ + /// + /// db上下文扩展类 + /// + public static class DbContextExtensions + { + public static IEnumerable SqlQuery(this DatabaseFacade facade, string sql, bool isAlias = false, params object[] parameters) where T : class, new() + { + var dt = SqlQuery(facade, sql, parameters); + if (isAlias) + return dt.ToEnumerableAlias(); + return dt.ToEnumerable(); + } + + public static async Task> SqlQueryAsync(this DatabaseFacade facade, string sql, bool isAlias = false, params object[] parameters) where T : class, new() + { + return await Task.Run(() => + { + var dt = SqlQuery(facade, sql, parameters); + if (isAlias) + return dt.ToEnumerableAlias(); + return dt.ToEnumerable(); + }); + } + + public static IEnumerable ToEnumerable(this DataTable dt) where T : class, new() + { + var propertyInfos = typeof(T).GetProperties(); + var ts = new T[dt.Rows.Count]; + var i = 0; + foreach (DataRow row in dt.Rows) + { + + try + { + var t = new T(); + foreach (var p in propertyInfos) + if (dt.Columns.IndexOf(p.Name) != -1 && row[p.Name] != DBNull.Value) + p.SetValue(t, row[p.Name], null); + + ts[i] = t; + i++; + } + catch (Exception ex) + { + + throw ex; + } + + + } + + return ts; + } + + /// + /// 对象属性别名的映射关系 + /// + /// + /// + /// + public static IEnumerable ToEnumerableAlias(this DataTable dt) where T : class, new() + { + var propertyInfos = typeof(T).GetProperties(); + var ts = new T[dt.Rows.Count]; + var i = 0; + foreach (DataRow row in dt.Rows) + { + var t = new T(); + foreach (var p in propertyInfos) + { + var attrs = p.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.Schema.ColumnAttribute), true); + if (attrs.Length > 0) + { + try + { + var name = ((System.ComponentModel.DataAnnotations.Schema.ColumnAttribute)attrs[0]).Name; + if (dt.Columns.IndexOf(name) != -1 && row[name] != DBNull.Value) + p.SetValue(t, row[name], null); + } + catch (Exception ex) + { + throw ex; + } + + + } + + } + + ts[i] = t; + i++; + } + + return ts; + } + + public static DataTable SqlQuery(this DatabaseFacade facade, string sql, params object[] parameters) + { + var cmd = CreateCommand(facade, sql, out var conn, parameters); + var reader = cmd.ExecuteReader(); + var dt = new DataTable(); + dt.Load(reader); + reader.Close(); + conn.Close(); + return dt; + } + + private static DbCommand CreateCommand(DatabaseFacade facade, string sql, out DbConnection dbConn, params object[] parameters) + { + var conn = facade.GetDbConnection(); + dbConn = conn; + conn.Open(); + var cmd = conn.CreateCommand(); + if (facade.IsMySql()) + { + cmd.CommandText = sql; + CombineParamsMySql(ref cmd, parameters); + } + if (facade.IsSqlServer()) + { + cmd.CommandText = sql; + CombineParams(ref cmd, parameters); + } + + return cmd; + } + + private static void CombineParams(ref DbCommand command, params object[] parameters) + { + if (parameters != null) + foreach (SqlParameter parameter in parameters) + { + if (!parameter.ParameterName.Contains("@")) + parameter.ParameterName = $"@{parameter.ParameterName}"; + command.Parameters.Add(parameter); + } + } + + private static void CombineParamsMySql(ref DbCommand command, params object[] parameters) + { + if (parameters != null) + foreach (MySqlConnector.MySqlParameter parameter in parameters) + { + if (!parameter.ParameterName.Contains("@")) + parameter.ParameterName = $"@{parameter.ParameterName}"; + command.Parameters.Add(parameter); + } + } + + public static bool ExecuteSqlCommand(this DatabaseFacade facade, string sql, params object[] parameters) + { + var cmd = CreateCommand(facade, sql, out var conn, parameters); + try + { + cmd.ExecuteNonQuery(); + return true; + } + catch (Exception ex) + { + var msg = ex.Message; + return false; + } + finally + { + conn.Close(); + } + } + + + public static IQueryable SortBy(this IQueryable source, string sortExpression) + { + if (source == null) + { + throw new ArgumentNullException("source"); + } + + string sortDirection = String.Empty; + string propertyName = String.Empty; + + sortExpression = sortExpression.Trim(); + int spaceIndex = sortExpression.Trim().IndexOf(" "); + if (spaceIndex < 0) + { + propertyName = sortExpression; + sortDirection = "ASC"; + } + else + { + propertyName = sortExpression.Substring(0, spaceIndex); + sortDirection = sortExpression.Substring(spaceIndex + 1).Trim(); + } + + if (String.IsNullOrEmpty(propertyName)) + { + return source; + } + + ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty); + MemberExpression property = Expression.Property(parameter, propertyName); + LambdaExpression lambda = Expression.Lambda(property, parameter); + + string methodName = (sortDirection == "ASC") ? "OrderBy" : "OrderByDescending"; + + Expression methodCallExpression = Expression.Call(typeof(Queryable), methodName, + new Type[] { source.ElementType, property.Type }, + source.Expression, Expression.Quote(lambda)); + + return source.Provider.CreateQuery(methodCallExpression); + } + } +} diff --git a/src/WMS.Web.Repositories/Configuration/Log/EFCoreLogger.cs b/src/WMS.Web.Repositories/Configuration/Log/EFCoreLogger.cs new file mode 100644 index 00000000..814d8fdf --- /dev/null +++ b/src/WMS.Web.Repositories/Configuration/Log/EFCoreLogger.cs @@ -0,0 +1,39 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace WMS.Web.Repositories.Configuration.Log +{ + public class EFCoreLogger : ILogger + { + private readonly string categoryName; + + public EFCoreLogger(string categoryName) => this.categoryName = categoryName; + + public bool IsEnabled(LogLevel logLevel) => true; + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + if (categoryName == "Microsoft.EntityFrameworkCore.Database.Command" && logLevel == LogLevel.Information) + { + var logContent = formatter(state, exception); + var str = logContent.ToLower(); + if ((str.Contains("update") || str.Contains("delete") || str.Contains("insert")) && + (str.Contains("t_sub_ppbom") || str.Contains("t_sub_ppbomentry") || str.Contains("t_sub_ppbomentry_l") + || str.Contains("t_prd_ppbom") || str.Contains("t_prd_ppbomentry") || str.Contains("t_prd_ppbomentry_l") + || str.Contains("t_eng_bom") || str.Contains("t_eng_bomchild"))) + { + if (!Directory.Exists("D:/Logs")) + Directory.CreateDirectory("D:/Logs"); + + logContent = "\r\n\r\n" + DateTime.Now + "--" + logContent; + //没有文件会自动创建,有就追加 + System.IO.File.AppendAllText("D:/Logs/增删改记录.txt", logContent); + } + } + } + public IDisposable BeginScope(TState state) => null; + } +} diff --git a/src/WMS.Web.Repositories/Configuration/Log/EFCoreLoggerProvider.cs b/src/WMS.Web.Repositories/Configuration/Log/EFCoreLoggerProvider.cs new file mode 100644 index 00000000..9660f52c --- /dev/null +++ b/src/WMS.Web.Repositories/Configuration/Log/EFCoreLoggerProvider.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; + +namespace WMS.Web.Repositories.Configuration.Log +{ + public class EFCoreLoggerProvider : ILoggerProvider + { + public ILogger CreateLogger(string categoryName) => new EFCoreLogger(categoryName); + public void Dispose() { } + } +} diff --git a/src/WMS.Web.Repositories/Configuration/RepositoryDbContext.cs b/src/WMS.Web.Repositories/Configuration/RepositoryDbContext.cs new file mode 100644 index 00000000..3a8ca3cf --- /dev/null +++ b/src/WMS.Web.Repositories/Configuration/RepositoryDbContext.cs @@ -0,0 +1,34 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Debug; +using System; +using System.Collections.Generic; +using System.Text; +using WMS.Web.Repositories.Configuration.Log; + +namespace WMS.Web.Repositories.Configuration +{ + /// + /// db上下文 + /// + public class RepositoryDbContext : DbContext + { + [Obsolete] + public readonly LoggerFactory LoggerFactory = new LoggerFactory(new[] { new DebugLoggerProvider() }); + public RepositoryDbContext(DbContextOptions options) : base(options) + { + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + LoggerFactory.AddProvider(new EFCoreLoggerProvider()); + base.OnConfiguring(optionsBuilder); + optionsBuilder.UseLoggerFactory(LoggerFactory).EnableSensitiveDataLogging(); + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + } + } +} diff --git a/src/WMS.Web.Repositories/DependencyInjection/AppBuilder.cs b/src/WMS.Web.Repositories/DependencyInjection/AppBuilder.cs new file mode 100644 index 00000000..690ad227 --- /dev/null +++ b/src/WMS.Web.Repositories/DependencyInjection/AppBuilder.cs @@ -0,0 +1,187 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.OpenApi.Models; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using WMS.Web.Core.Help; +using WMS.Web.Domain.IService.Public; +using WMS.Web.Domain.Mappers; +using WMS.Web.Domain.Options; +using WMS.Web.Domain.Services.Public; + +namespace WMS.Web.Repositories.DependencyInjection +{ + /// + /// App服务 + /// + public class AppBuilder + { + /// + /// 服务集合 + /// + public IServiceCollection Services { get; } + + public IConfiguration Configuration { get; } + + public IWebHostEnvironment WebHostEnvironment { get; } + + /// + /// asf 服务 + /// + /// + public AppBuilder(IServiceCollection services, IConfiguration configuration, IWebHostEnvironment webHostEnvironment) + { + Services = services; + Configuration = configuration; + WebHostEnvironment = webHostEnvironment; + } + + /// + /// 编译服务 + /// + public void Build() + { + this.AddCors(); + this.InitRedis(); + this.AddSwagger(); + this.AddOther(); + this.AddConfigOptions(); + this.AddServiceRepositories(); + } + /// + /// 其它功能注入:AutoMapper等其它 + /// + private void AddOther() + { + Services.AddMvc().AddNewtonsoftJson(opt => + { + //// 忽略循环引用 + //opt.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); + //// 不使用驼峰 + //opt.SerializerSettings.ContractResolver = new DefaultContractResolver(); + }); + + //AutoMapper映射关系 + Services.AddAutoMapper(typeof(AppMapper).Assembly); + } + + /// + /// 跨域注入 + /// + private void AddCors() + { + // 全局跨域注入 + Services.AddCors(opt => + { + string[] urls = Configuration.GetSection("AllowedCores").Value.Split(','); + opt.AddPolicy("AllowAllOrigin", builder => + { + + builder.AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials() + .WithOrigins(urls); + + }); + }); + } + + /// + /// 初始化redis + /// + private void InitRedis() + { + var option = Configuration.GetSection("AppOptions").Get(); + var option_soa = Configuration.GetSection("SoaOptions").Get(); + //初始化redis + RedisClient.redisClient.InitConnect(option.RedisConnectionString); + Services.AddHttpClient("ops_client", c => + { + c.BaseAddress = new Uri(option_soa.Url); + }); + } + + /// + /// 注册swagger + /// + private void AddSwagger() + { + if (WebHostEnvironment.IsDevelopment()) + { + // 注册Swagger服务 + Services.AddSwaggerGen(c => + { + // 添加文档信息 + c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo + { + Title = "WMS", + Version = "v1", + Description = "WMS-Api" + }); + #region 读取xml信息 + // 使用反射获取xml文件。并构造出文件的路径 + //// 启用xml注释. 该方法第二个参数启用控制器的注释,默认为false. + foreach (var file in Directory.GetFiles(AppContext.BaseDirectory, "WMS.*.xml")) c.IncludeXmlComments(file, true); + #endregion + + #region 启用swagger验证功能 + //添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称一致即可,CoreAPI。 + var securit = new OpenApiSecurityRequirement() + { + { + new OpenApiSecurityScheme + { + Reference=new OpenApiReference { Type=ReferenceType.SecurityScheme,Id= "WMSAPI" } + }, + new string[] { } + } + }; + c.AddSecurityRequirement(securit); + c.AddSecurityDefinition("WMSAPI", new OpenApiSecurityScheme + { + Description = "JWT授权(数据将在请求头中进行传输) 在下方输入Bearer {token} 即可", + Name = "Authorization",//jwt默认的参数名称 + In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中) + Type = SecuritySchemeType.ApiKey + }); + #endregion + + }); + } + } + + /// + /// 系统配置 + /// + private void AddConfigOptions() + { + //系统配置注册 + Services.AddOptions(); + Services.Configure(Configuration.GetSection("AppOptions")); + Services.AddOptions(); + Services.Configure(Configuration.GetSection("SoaOptions")); + Services.AddOptions(); + Services.Configure(Configuration.GetSection("HttpOptions")); + } + + /// + /// 注入服务层 + /// + /// + private void AddServiceRepositories() + { + Services.AddSingleton(); + Services.AddTransient(); + //注入服务 + Services.AddTransient(); + Services.AddTransient(); + Services.AddTransient(); + } + } +} diff --git a/src/WMS.Web.Repositories/DependencyInjection/AppBuilderExtensions.cs b/src/WMS.Web.Repositories/DependencyInjection/AppBuilderExtensions.cs new file mode 100644 index 00000000..b5ad9b17 --- /dev/null +++ b/src/WMS.Web.Repositories/DependencyInjection/AppBuilderExtensions.cs @@ -0,0 +1,34 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Text; +using WMS.Web.Repositories.Configuration; +using WMS.Web.Repositories.DependencyInjection; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class AppBuilderExtensions + { + /// + /// 配置数据库 + /// + /// + /// + /// + public static AppBuilder AddDbContext(this AppBuilder builder, Action configureDbContext) + { + builder.Services.AddDbContext(configureDbContext); + builder.Services.AddRepositories(); + return builder; + } + + /// + /// 注入仓储层 + /// + /// + private static void AddRepositories(this IServiceCollection services) + { + services.AddHttpContextAccessor(); + } + } +} diff --git a/src/WMS.Web.Repositories/DependencyInjection/AuthorizationTokenSecurityPolicy.cs b/src/WMS.Web.Repositories/DependencyInjection/AuthorizationTokenSecurityPolicy.cs new file mode 100644 index 00000000..716f1866 --- /dev/null +++ b/src/WMS.Web.Repositories/DependencyInjection/AuthorizationTokenSecurityPolicy.cs @@ -0,0 +1,168 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Memory; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WMS.Web.Core.Dto.Login; +using WMS.Web.Domain.IService.Public; +using WMS.Web.Domain.Services.Public; + +namespace WMS.Web.Repositories.DependencyInjection +{ + /// + /// token 黑名单中间件 + /// + public class AuthorizationTokenSecurityPolicy + { + private readonly RequestDelegate _next; + private readonly IMemoryCache _cache; + private DateTime _refreshTime = DateTime.Now.AddYears(-5); + private readonly RedisClientService _redisClientService; + + /// + /// token黑名单中间件 + /// + /// + /// + public AuthorizationTokenSecurityPolicy(RequestDelegate next, IMemoryCache cache, RedisClientService redisClientService) + { + _next = next; + _cache = cache; + _redisClientService = redisClientService; + } + + /// + /// 事件 + /// + /// + /// + public async Task Invoke(HttpContext context, ILoginService loginService) + { + string authorization = context.Request.Headers["Authorization"]; + string path = context.Request.Path.Value.ToLower(); + string[] pathlist = path.Split('/'); + bool isLogin = pathlist.Where(x => x == "login" || x.ToLower() == "heart" || x.ToLower() == "test").Any(); + if (isLogin) + { + context.Response.StatusCode = 200; + await _next(context); + return; + } + + if (string.IsNullOrEmpty(authorization)) + { + context.Response.StatusCode = 401; + var result = JsonConvert.SerializeObject(new { status = 401, data = string.Empty, message = "授权失败,请重新登录" }); + context.Response.ContentType = "application/json;charset=utf-8"; + await context.Response.WriteAsync(result); + return; + } + else + { + string token = string.Empty; + if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) + { + token = authorization.Substring("Bearer ".Length).Trim(); + } + + //判断前端过来的token + if (string.IsNullOrEmpty(token)) + { + context.Response.StatusCode = 401; + var result = JsonConvert.SerializeObject(new { status = 401, data = string.Empty, message = "授权失败,请重新登录" }); + context.Response.ContentType = "application/json;charset=utf-8"; + await context.Response.WriteAsync(result); + return; + } + + //1.验证是否有登录数据缓存 + var logininfo = _redisClientService.GetStringKey($"ops_login_{token}"); + if (logininfo == null) + { + context.Response.StatusCode = 401; + var result = JsonConvert.SerializeObject(new { status = 401, data = string.Empty, message = "授权失败,请重新登录" }); + context.Response.ContentType = "application/json;charset=utf-8"; + await context.Response.WriteAsync(result); + return; + + } + else + { + //2.判断缓存的token 过期时间 + if (!string.IsNullOrEmpty(logininfo.TokenInfo.Token) && logininfo.TokenInfo.Expired.AddMinutes(-10) <= DateTime.Now) + { + var refreshtokeninfo = RefreshToken(logininfo.TokenInfo.Token, logininfo.TokenInfo.RefreshToken, loginService); + + if (!refreshtokeninfo) + { + RemoveRedisLoginInfo(token); + } + } + //3.验证检查是否有黑名单的token缓存 + string blacktoken = _redisClientService.GetStringKey($"ops_black_token_{logininfo.UserInfo.UcId}"); + if (string.IsNullOrEmpty(blacktoken)) + { + context.Response.StatusCode = 200; + await _next(context); + } + else + { + RemoveRedisLoginInfo(token); + context.Response.StatusCode = 403; + var result = JsonConvert.SerializeObject(new { status = 403, data = string.Empty, message = "拒绝用户证书试图访问此web站点,请与站点管理员联系以建立用户证书权限" }); + context.Response.ContentType = "application/json;charset=utf-8"; + await context.Response.WriteAsync(result); + } + } + if (context.Response.StatusCode == 401 || context.Response.StatusCode == 403) + { + //调用单点的退出接口 + var dto = new LoginOutDto() + { + UcId = logininfo.UserInfo.UcId.ToString(), + SessionId = logininfo.UserInfo.SeesionId, + Token = logininfo.TokenInfo.Token, + AccessToken = logininfo.TokenInfo.PhpToken, + ExpiresIn = logininfo.TokenInfo.Expired + + }; + var res = await loginService.LoginOutAsync(dto); + return; + } + } + } + + /// + /// 过期,或者失效,移出token + /// + /// + private void RemoveRedisLoginInfo(string token) + { + if (!string.IsNullOrEmpty(token)) + { + var info = _redisClientService.GetStringKey($"ops_login_{token}"); + if (info != null) + { + _redisClientService.RemoveStringKey($"ops_login_{token}"); + } + } + } + + /// + /// 刷新token + /// + /// + /// + private bool RefreshToken(string OldToken, string RefreshToken, ILoginService _loginService) + { + var res = _loginService.RefreshToken(OldToken, RefreshToken); + if (!res.Result.Success) + return false; + else + return true; + } + } +} diff --git a/src/WMS.Web.Repositories/DependencyInjection/ErrorHandlingMiddleware.cs b/src/WMS.Web.Repositories/DependencyInjection/ErrorHandlingMiddleware.cs new file mode 100644 index 00000000..dfab979b --- /dev/null +++ b/src/WMS.Web.Repositories/DependencyInjection/ErrorHandlingMiddleware.cs @@ -0,0 +1,85 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading.Tasks; + +namespace WMS.Web.Repositories.DependencyInjection +{ + /// + /// 统一全局错误拦截 + /// + public class ErrorHandlingMiddleware + { + private readonly RequestDelegate next; + private readonly ILogger _logger; + + /// + /// 统一错误处理中间件 + /// + public ErrorHandlingMiddleware(RequestDelegate next, ILogger logger) + { + this.next = next; + _logger = logger; + } + private string bodyStr = ""; + /// + /// 激活 + /// + /// + /// + public async Task Invoke(HttpContext context) + { + try + { + //默认 请求body只能读取一次 所以在这里需要手动把他设置成读取多次 并且 不能使用using 释放 + context.Request.EnableBuffering(); + StreamReader requestReader = new StreamReader(context.Request.Body, Encoding.UTF8); + bodyStr = await requestReader.ReadToEndAsync(); + context.Request.Body.Seek(0, SeekOrigin.Begin); + + await next(context); + } + catch (Exception ex) + { + // var statusCode = context.Response.StatusCode; + var statusCode = 500; + if (ex is ArgumentException) statusCode = 200; + + _logger.LogError($"统一拦截异常处理: {ex.Message}, StackTrace:{ex.StackTrace},Path:{context.Request.Path},Parame:{bodyStr}"); + + await HandleExceptionAsync(context, statusCode, "服务器错误,不能执行此请求,请稍后重试,若问题一直存在,请与站点管理员联系"); + // await HandleExceptionAsync(context, statusCode, "服务器错误"); + } + finally + { + var statusCode = context.Response.StatusCode; + var msg = ""; + // if (statusCode == 401) + // { + // msg = "未授权"; + // } + if (statusCode == 404) + msg = "服务器暂无响应,请稍后重试,若问题一直存在,请与站点管理员联系"; + else if (statusCode == 502) msg = "网关出错,请与站点管理员联系"; + // else if (statusCode != 200) + // { + // msg = "未知错误"; + // } + if (!string.IsNullOrWhiteSpace(msg)) await HandleExceptionAsync(context, statusCode, msg); + } + } + + private static Task HandleExceptionAsync(HttpContext context, int statusCode, string msg) + { + string data = null; + var result = JsonConvert.SerializeObject(new { status = statusCode, result = data, message = msg }); + context.Response.StatusCode = statusCode; + context.Response.ContentType = "application/json;charset=utf-8"; + return context.Response.WriteAsync(result); + } + } +} diff --git a/src/WMS.Web.Repositories/DependencyInjection/ServiceCollectionExtensions.cs b/src/WMS.Web.Repositories/DependencyInjection/ServiceCollectionExtensions.cs new file mode 100644 index 00000000..af88b811 --- /dev/null +++ b/src/WMS.Web.Repositories/DependencyInjection/ServiceCollectionExtensions.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Text; +using WMS.Web.Repositories.DependencyInjection; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class ServiceCollectionExtensions + { + /// + /// 添加app框架 + /// + /// + /// + /// + public static IServiceCollection AddApp(this IServiceCollection services, IConfiguration configuration, IWebHostEnvironment webHostEnvironment, Action startupAction) + { + services.AddAppCore(configuration, webHostEnvironment, startupAction); + return services; + } + + + /// + /// 添加app核心服务 + /// + /// + /// ASF启动配置函数 + /// + internal static IServiceCollection AddAppCore(this IServiceCollection services, IConfiguration configuration, IWebHostEnvironment webHostEnvironment, Action startupAction) + { + var builder = new AppBuilder(services, configuration, webHostEnvironment); + startupAction?.Invoke(builder); + builder.Build(); + return services; + } + + } +} diff --git a/src/WMS.Web.Repositories/WMS.Web.Repositories.csproj b/src/WMS.Web.Repositories/WMS.Web.Repositories.csproj index 9b67ea74..be24beb1 100644 --- a/src/WMS.Web.Repositories/WMS.Web.Repositories.csproj +++ b/src/WMS.Web.Repositories/WMS.Web.Repositories.csproj @@ -4,11 +4,6 @@ netcoreapp3.1 - - - - -