Compare commits

..

10 Commits

Author SHA1 Message Date
lihanbo 1a362319d0 Default dev db for sqlite 2024-10-16 11:28:39 +08:00
lihanbo 448cb878ba Config DefaultConnection 2024-10-16 11:28:17 +08:00
lihanbo 215540ca1c Add Default CURD impl 2024-10-16 11:27:57 +08:00
lihanbo 0d5dc03030 Use IModule register modules 2024-10-16 11:27:14 +08:00
lihanbo cf7ebb3cbc Add CodeFirst helper 2024-10-16 11:25:57 +08:00
lihanbo 5f9f86663e Update allow use GetAll 2024-10-16 11:25:32 +08:00
lihanbo 963649b2b7 FIx error `The logger is already frozen` 2024-10-16 11:24:49 +08:00
lihanbo 7a6c1d8481 Fix typo 2024-10-16 11:24:29 +08:00
lihanbo 19a612160e FIx error `The logger is already frozen` 2024-10-16 11:24:10 +08:00
lihanbo 59e8845568 Add Module interface. use ConfigureModule method to build Module 2024-10-16 11:17:16 +08:00
16 changed files with 333 additions and 125 deletions

View File

@ -6,7 +6,7 @@ using Serilog;
using Serilog.Core;
namespace LFlow.Home.Controllers;
public class HomeController(IHomeService<HomeDto, string> service, ILogger logger) : BaseController
public class HomeController(IHomeService<HomeDto, string> service, ILogger logger)
{
[HttpGet]
public string Home(string id)

30
LFlow.Home/HomeModule.cs Normal file
View File

@ -0,0 +1,30 @@
using System;
using System.Reflection;
using LFlow.Base.BusinessInterface;
using LFlow.Base.Interfaces;
using LFlow.Base.Utils;
using LFlow.Home.Models.DataModels;
using LFlow.Home.Models.DtoModel;
using LFlow.Home.Services;
using Microsoft.Extensions.DependencyInjection;
namespace LFlow.Home;
public class HomeModule : IModule
{
public void ConfigureModule(IServiceCollection services)
{
// 将HomeModel注册到CodeFirst将会在程序启动后自动创建表
CodeFirst.AddType(typeof(HomeModel));
var assembly = Assembly.GetAssembly(typeof(HomeService))!;
var types = assembly.GetTypes().ToList();
RegisterModule.RegisterAllService(types, services);
RegisterModule.RegisterAllRepo(types, services);
RegisterModule.RegisterAllModule(types, services);
services.AddControllers().AddApplicationPart(assembly);
Console.WriteLine("HomeModule ConfigureModule");
}
}

View File

@ -5,11 +5,26 @@ namespace LFlow.Home.Models.DtoModel;
public class HomeDto : IModel
{
public string? Id { get; set; }
public string? Id
{
get; set;
}
public string? ModuleName
{
get; set;
}
public string? ModuleUrl
{
get; set;
}
public string? ModuleVer
{
get; set;
}
public override string ToString()
{
return $"HomeDto {Id}";
return $"HomeDto {Id} _ {ModuleName} _ {ModuleUrl} _ {ModuleVer}";
}
}

View File

@ -1,4 +1,5 @@
using System;
using LFlow.Base.Default;
using LFlow.Base.Interfaces;
// using LFlow.Interfaces;
@ -7,33 +8,21 @@ using SqlSugar;
namespace LFlow.Home.Repositorys;
public class HomeRepo(ISqlSugarClient db) : IRepo<HomeModel, string>
public class HomeRepo(ISqlSugarClient db) : DefaultCurdRepo<HomeModel, string>(db)
{
public HomeModel Delete(string id)
{
throw new NotImplementedException();
}
public HomeModel Get(string id)
{
return new HomeModel
{
Id = id
};
}
public HomeModel SaveOrUpdate(HomeModel entity, bool isUpdate)
{
throw new NotImplementedException();
}
public List<HomeModel> Search(HomeModel whereObj)
{
throw new NotImplementedException();
}
public List<string> WhereSearchId(HomeModel whereObj)
{
throw new NotImplementedException();
}
/// <summary>
/// 查询
/// </summary>
/// <param name="whereObj"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override List<HomeModel> Search(HomeModel whereObj) => throw new NotImplementedException();
/// <summary>
/// 根据条件查询ID
/// </summary>
/// <param name="whereObj"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override List<string> WhereSearchId(HomeModel whereObj) => throw new NotImplementedException();
}

View File

@ -7,31 +7,33 @@ using LFlow.Home.Models.DataModels;
using LFlow.Home.Models.DtoModel;
using LFlow.Base.BusinessInterface;
using Serilog;
using Microsoft.AspNetCore.Mvc;
namespace LFlow.Home.Services;
public class HomeService(IRepo<HomeModel, string> repo, ILogger logger) : IHomeService<HomeDto, string>
public class HomeService(IRepo<HomeModel, string> repo, ILogger logger) : BaseController, IHomeService<HomeDto?, string>
{
public HomeDto DeleteById(string id)
[HttpGet]
public HomeDto? DeleteById(string id)
{
var result = repo.Delete(id);
return Mapper.Map<HomeDto>(result);
}
public HomeDto GetById(string id)
[HttpGet]
public HomeDto? GetById(string id)
{
logger.Information($"GetById id -> {id}");
var result = repo.Get(id);
return Mapper.Map<HomeDto>(result);
}
public HomeDto Save(HomeDto entity)
[HttpPost]
public HomeDto? Save(HomeDto entity)
{
var result = repo.SaveOrUpdate(Mapper.Map<HomeModel>(entity), false);
return Mapper.Map<HomeDto>(result);
}
public List<HomeDto> Search(HomeDto whereObj)
[HttpGet]
public List<HomeDto>? Search(HomeDto whereObj)
{
throw new NotImplementedException();
}

View File

@ -1,41 +1,25 @@
using System;
using LFlow.Base.Default;
using LFlow.Base.Interfaces;
using LFlow.User.Model.DataModel;
using SqlSugar;
namespace LFlow.User.Repositorys;
public class UserRepo(ISqlSugarClient db) : IRepo<UserModel, string>
public class UserRepo(ISqlSugarClient db) : DefaultCurdRepo<UserModel, string>(db)
{
public UserModel Delete(string id)
{
throw new NotImplementedException();
}
public UserModel Get(string id)
{
return new UserModel
{
UserID = id,
UserName = "Test User",
UserNickName = "Tester",
EmailAddress = "Test@Ling.chat",
};
}
public UserModel SaveOrUpdate(UserModel entity, bool isUpdate)
{
throw new NotImplementedException();
}
public List<UserModel> Search(UserModel whereObj)
{
throw new NotImplementedException();
}
public List<string> WhereSearchId(UserModel whereObj)
{
throw new NotImplementedException();
}
/// <summary>
/// 查询
/// </summary>
/// <param name="whereObj"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override List<UserModel> Search(UserModel whereObj) => throw new NotImplementedException();
/// <summary>
/// 根据条件查询ID
/// </summary>
/// <param name="whereObj"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override List<string> WhereSearchId(UserModel whereObj) => throw new NotImplementedException();
}

View File

@ -7,9 +7,9 @@ namespace LFlow.Base;
public class App
{
public static IServiceCollection? services;
private static IServiceProvider? serviceProvider => services?.BuildServiceProvider();
private static IServiceProvider? ServiceProvider => services?.BuildServiceProvider();
public static T? GetService<T>()
{
return serviceProvider.GetService<T>();
return ServiceProvider!.GetService<T>();
}
}

View File

@ -0,0 +1,40 @@
using System;
using System.Reflection;
using LFlow.Base.Interfaces;
namespace LFlow.Base.Default;
/// <summary>
/// 默认的CURD操作
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="K"></typeparam>
public abstract class DefaultCurd<T, K> where T : IModel, IDataModel
{
private readonly IRepo<T, K> _repo;
public DefaultCurd(IRepo<T, K> repo)
{
_repo = repo;
}
public virtual T Add(T model)
{
return _repo.SaveOrUpdate(model, false);
}
public virtual int Delete(K id)
{
return _repo.Delete(id);
}
public virtual T Update(T model)
{
return _repo.SaveOrUpdate(model, true);
}
public virtual T Get(K id)
{
return _repo.Get(id);
}
public virtual List<T> GetAll(int pageIndex, int pageSize, ref int pageTotal)
{
return _repo.GetAll(pageIndex, pageSize, ref pageTotal);
}
public abstract List<T> GetWhere(T WhereObject);
}

View File

@ -0,0 +1,50 @@
using System;
using LFlow.Base.Interfaces;
using SqlSugar;
namespace LFlow.Base.Default;
public abstract class DefaultCurdRepo<T, K> : IRepo<T, K> where T : class, IDataModel, new()
{
private readonly ISqlSugarClient _client;
public DefaultCurdRepo(ISqlSugarClient client)
{
_client = client;
}
public virtual int Delete(K id)
{
if (Get(id) != null)
{
return _client.Deleteable<T>().In(id).ExecuteCommand();
}
else
{
throw new Exception("删除的对象不存在");
}
}
public virtual T Get(K id)
{
return _client.Queryable<T>().InSingle(id);
}
public List<T> GetAll(int pageIndex, int pageSize, ref int pageTotal)
{
return _client.Queryable<T>().ToPageList(pageIndex, pageSize, ref pageTotal);
}
public virtual T SaveOrUpdate(T entity, bool isUpdate)
{
if (isUpdate)
{
_client.Updateable(entity).ExecuteCommand();
}
else
{
_client.Insertable(entity).ExecuteCommand();
}
return entity;
}
public abstract List<T> Search(T whereObj);
public abstract List<K> WhereSearchId(T whereObj);
}

View File

@ -0,0 +1,10 @@
using System;
namespace LFlow.Base.Interfaces;
/// <summary>
/// 模块接口
/// </summary>
public interface IModule
{
void ConfigureModule(IServiceCollection services);
}

View File

@ -20,13 +20,21 @@ public interface IRepo<T, K> where T : IDataModel
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
T Delete(K id);
int Delete(K id);
/// <summary>
/// 保存与更新
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
T SaveOrUpdate(T entity, bool isUpdate);
/// <summary>
/// 获取所有对象列表(默认分页)
/// </summary>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
List<T> GetAll(int pageIndex, int pageSize, ref int pageTotal);
/// <summary>
/// 根据条件搜索对象列表
/// </summary>

BIN
LFlow/LFlow-dev.db Normal file

Binary file not shown.

View File

@ -1,4 +1,6 @@
using System.Reflection;
using LFlow.Base.Interfaces;
using LFlow.Base.Utils;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
@ -56,7 +58,13 @@ public static class Program
});
});
builder.Host.UseSerilog();
builder.Host.UseSerilog((context, services, config) =>
{
config.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext();
// .WriteTo.Console();
}, true);
// init App.service
App.services = builder.Services;
var app = builder.Build();
@ -74,6 +82,13 @@ public static class Program
u.DocumentTitle = "LFlow";
});
}
// 在启动后调用Sqlsugar进行CodeFirst
// 挂载启动后事件
app.Services.GetRequiredService<IHostApplicationLifetime>().ApplicationStarted.Register(() =>
{
Log.Logger.Information("ApplicationStarted");
CodeFirst.InitTable();
});
app.Run();
}
@ -87,18 +102,20 @@ public static class Program
ConnectionString = "DataSource=LFlow-dev.db",
IsAutoCloseConnection = true,
},
db =>
{
//单例参数配置,所有上下文生效
db.Aop.OnLogExecuting = (sql, pars) =>
{
//获取作IOC作用域对象
var appServive = s.GetService<IHttpContextAccessor>();
// var obj = appServive?.HttpContext?.RequestServices.GetService<Log>();
// Console.WriteLine("AOP" + obj.GetHashCode());
Console.WriteLine($"{appServive?.HttpContext?.Request.Path}:{sql}\r\n{pars}");
};
});
db =>
{
//单例参数配置,所有上下文生效
db.Aop.OnLogExecuting = (sql, pars) =>
{
//获取作IOC作用域对象
var appServive = s.GetService<IHttpContextAccessor>();
// var obj = appServive?.HttpContext?.RequestServices.GetService<Log>();
// Console.WriteLine("AOP" + obj.GetHashCode());
Console.WriteLine($"{appServive?.HttpContext?.Request.Path}:{sql}\r\n{pars}");
};
});
sqlSugar.DbMaintenance.CreateDatabase();
return sqlSugar;
});
}
@ -117,43 +134,27 @@ public static class Program
Log.Logger.Information($"Load file -> {file}...");
var assembly = Assembly.LoadFile(file);
var types = assembly.GetTypes();
bool isUseController = false;
// bool isUseController = false;
foreach (var type in types)
{
// Console.WriteLine(type);
if (type.IsClass && !type.IsAbstract)
{
var interfaces = type.GetInterfaces();
foreach (var inter in interfaces)
if (interfaces.Contains(typeof(IModule)))
{
if (inter.Name.Contains("IRepo"))
{
//注册数据仓库
services.AddScoped(inter, type);
}
if (inter.Name.Contains(type.Name))
{
//注册服务
services.AddScoped(inter, type);
}
if (inter.Name.Contains("IController"))
{
isUseController = true;
}
if (inter.Name.Equals("IDataModel"))
{
}
Log.Logger.Information($"\tFound IModule -> {type.FullName}");
var module = Activator.CreateInstance(type) as IModule;
module.ConfigureModule(services);
}
}
}
if (isUseController)
{
Log.Logger.Information($"\tAdd Controllers for {assembly.FullName}");
// 添加Controller
services.AddControllers().AddApplicationPart(assembly);
}
// if (isUseController)
// {
// Log.Logger.Information($"\tAdd Controllers for {assembly.FullName}");
// // 添加Controller
// services.AddControllers().AddApplicationPart(assembly);
// }
Log.Logger.Information("done.\r\n");
}
}
@ -164,4 +165,6 @@ public static class Program
}
}
}

View File

@ -1,25 +1,32 @@
using System;
using System.Collections.Concurrent;
using System.Net;
using Serilog;
using SqlSugar;
namespace LFlow.Base.Utils;
public static class CodeFirst
{
private static List<Type> _tableTypes = new List<Type>();
internal static void RegisterTable(Type type)
// 线程安全的类型列表
private static readonly ConcurrentBag<Type> _types = new();
public static void AddType(Type type)
{
if (_tableTypes.Contains(type))
_types.Add(type);
}
internal static void InitTable()
{
var logger = App.GetService<Serilog.ILogger>()!;
var db = App.GetService<ISqlSugarClient>()!;
foreach (var type in _types)
{
return;
}
else
{
_tableTypes.Add(type);
db.CodeFirst.InitTables(type);
logger.Information($"Init table {type.Name} success");
}
}
internal static void DBSeed()
{
internal static void InitDBSeed()
{
//TODO: Seed data
}
}

View File

@ -0,0 +1,67 @@
using System;
using LFlow.Base.Interfaces;
namespace LFlow.Base.Utils;
public static class RegisterModule
{
public static void RegisterAllModule(this List<Type> types, IServiceCollection services)
{
foreach (var type in types)
{
if (type.IsAbstract || !type.IsClass)
{
continue;
}
var interfaces = type.GetInterfaces();
foreach (var inter in interfaces)
{
if (inter.Name.Equals("IDataModel"))
{
services.AddScoped(inter, type);
}
}
}
}
public static void RegisterAllService(this List<Type> types, IServiceCollection services)
{
foreach (var type in types)
{
if (type.IsAbstract || !type.IsClass)
{
continue;
}
var interfaces = type.GetInterfaces();
foreach (var inter in interfaces)
{
if (inter.Name.Contains(type.Name) && inter.Name.StartsWith('I') && inter.Name.Contains("Service"))
{
//注册服务
services.AddScoped(inter, type);
}
}
}
}
public static void RegisterAllRepo(this List<Type> types, IServiceCollection services)
{
foreach (var type in types)
{
if (type.IsAbstract || !type.IsClass)
{
continue;
}
var interfaces = type.GetInterfaces();
foreach (var inter in interfaces)
{
if (inter.Name.Contains("IRepo"))
{
//注册数据仓库
services.AddScoped(inter, type);
}
}
}
}
}

View File

@ -14,5 +14,8 @@
}
]
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Data Source=192.168.3.85;Initial Catalog=PluginAdmin-dev;User Id=sa;Password=Sa1234;Encrypt=True;TrustServerCertificate=True"
}
}