LFlow/LFlow.Base/Program.cs

271 lines
9.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using LFlow.Base.Interfaces;
using LFlow.Base.Utils;
using LFlow.Cache;
using LFlow.InternalEventBus;
using LFlow.Middleware;
using LFlow.Middleware.Register;
using Serilog;
using Serilog.Events;
using SqlSugar;
using System.Reflection;
namespace LFlow.Base;
public static class Program
{
public static void Main(string[] args)
{
// 先用Serilog的BootstrapLogger
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateBootstrapLogger();
ConfigDllLoader();
var builder = WebApplication.CreateBuilder(args);
// 添加到Service中
builder.Services.AddSerilog((services, lc) => lc
.ReadFrom.Configuration(builder.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext()
// .WriteTo.Console()
);
builder.Services.AddLogging(loggingBuilder =>
{
loggingBuilder.AddSerilog(Log.Logger, dispose: true);
});
builder.Services.AddResponseCompression();
builder.Services.AddResponseCaching();
Log.Logger.Information("LoadSubService");
builder.Services.LoadSubService();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHttpContextAccessor();
Log.Logger.Information("ConfigureSqlSugar");
builder.Services.ConfigureSqlSugar();
builder.Services.AddControllers();
builder.Services.AddSwaggerGen(u =>
{
u.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
{
Version = "Ver.1",
Title = "LFlow",
Description = "LFlow api test and document",
Contact = new Microsoft.OpenApi.Models.OpenApiContact
{
Name = "ling",
Email = "noemail@ling.chat"
}
});
});
// 配置跨域策略
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAny", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
//// 使用Serilog此处为了修复 `The logger is already frozen` 的问题重新配置Serilog
//builder.Host.UseSerilog((context, services, config) =>
//{
// config.ReadFrom.Configuration(context.Configuration)
// .ReadFrom.Services(services)
// .Enrich.FromLogContext();
// // .WriteTo.Console();
//}, true);
builder.Host.UseSerilog(Log.Logger);
// 注册中间件
builder.Services.RegisterMiddlewares(App.SubServiceAssembly);
// 注册内部事件总线
builder.Services.AddInternalEventBus(App.SubServiceAssembly);
// 注册自身缓存器
builder.Services.AddSelfCache();
// init App.service
App.services = builder.Services;
var app = builder.Build();
app.UseSerilogRequestLogging(options =>
{
// 配置日志级别
options.GetLevel = (httpContext, elapsed, ex) => LogEventLevel.Information;
});
app.MapControllers();
// 添加根目录映射
app.MapGet("/", async context =>
{
context.Response.ContentType = "text/html";
await context.Response.SendFileAsync(Path.Combine(app.Environment.WebRootPath, "index.html"));
});
// if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(u =>
{
u.DocumentTitle = "LFlow";
});
}
// 在启动后调用Sqlsugar进行CodeFirst
// 挂载启动后事件
app.Services.GetRequiredService<IHostApplicationLifetime>().ApplicationStarted.Register(async () =>
{
Log.Logger.Information("ApplicationStarted");
CodeFirst.InitTable();
InternalEventBus.InternalEventBus.Publish("Init", "ApplicationStarted");
});
// 启用自定义中间件
app.UseLFlowMiddleware();
// 启用内部事件总线
app.UseInternalEventBus();
// 启用缓存
app.UseResponseCaching();
// 启用压缩
app.UseResponseCompression();
// 启用静态文件支持
app.UseStaticFiles();
app.UseCors("AllowAny");
app.Run();
}
public static void ConfigureSqlSugar(this IServiceCollection services)
{
services.AddSingleton<ISqlSugarClient>(s =>
{
SqlSugarScope sqlSugar = new(new ConnectionConfig()
{
DbType = SqlSugar.DbType.Sqlite,
ConnectionString = "DataSource=LFlow-dev.db",
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute //从实体特性中读取主键自增列信息
},
db =>
{
//单例参数配置,所有上下文生效
db.Aop.OnLogExecuting = (sql, pars) =>
{
//获取作IOC作用域对象
var appServive = s.GetService<IHttpContextAccessor>();
var log = s.GetService<Serilog.ILogger>();
// var obj = appServive?.HttpContext?.RequestServices.GetService<Log>();
// Console.WriteLine("AOP" + obj.GetHashCode());
log?.Debug($"{appServive?.HttpContext?.Request.Path}:{sql}\r\n{pars}");
};
});
sqlSugar.DbMaintenance.CreateDatabase();
return sqlSugar;
});
}
/// <summary>
/// 从子文件夹中加载DLL
/// </summary>
public static void LoadSubService(this IServiceCollection services)
{
var path = Path.Combine(AppContext.BaseDirectory, "Services");
// Console.WriteLine(path);
var files = Directory.GetFiles(path, "*.dll");
try
{
foreach (var file in files)
{
try
{
bool isModule = false;
Log.Logger.Information($"Load file -> {file}...");
var assembly = Assembly.LoadFile(file);
var types = assembly.GetTypes();
// bool isUseController = false;
foreach (var type in types)
{
// Console.WriteLine(type);
if (type.IsClass && !type.IsAbstract)
{
var interfaces = type.GetInterfaces();
if (interfaces.Contains(typeof(IModule)))
{
Log.Logger.Information($"\tFound IModule -> {type.FullName}");
var module = Activator.CreateInstance(type) as IModule;
module?.ConfigureModule(services);
isModule = true;
}
}
}
// if (isUseController)
// {
// Log.Logger.Information($"\tAdd Controllers for {assembly.FullName}");
// // 添加Controller
// services.AddControllers().AddApplicationPart(assembly);
// }
if (isModule)
{
App.SubServiceAssembly.Add(assembly);
}
Log.Logger.Information("done.\r\n");
}
catch (Exception ex)
{
Log.Logger.Error(ex, $"Load file -> {file} error.");
}
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public static void ConfigDllLoader()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
var assemblyName = new AssemblyName(args.Name);
// 判断是否已经被加载
var loadedAssembly = AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(a => a.FullName == assemblyName.FullName);
if (loadedAssembly != null)
{
Log.Logger?.Information($"Assembly {assemblyName.Name} has been loaded.");
return loadedAssembly;
}
// 从当前路径下加载
var path = Path.Combine(AppContext.BaseDirectory, $"{assemblyName.Name}.dll");
if (File.Exists(path))
{
Log.Logger?.Information($"Assembly {assemblyName.Name} has been loaded for {path}.");
return Assembly.LoadFile(path);
}
// 从Service文件夹中加载
path = Path.Combine(AppContext.BaseDirectory, "Service", $"{assemblyName.Name}.dll");
if (File.Exists(path))
{
Log.Logger?.Information($"Assembly {assemblyName.Name} has been loaded for {path}.");
return Assembly.LoadFile(path);
}
Log.Logger?.Error($"Assembly {assemblyName.Name} not found.");
return null;
};
}
}