feat: 添加代码生成器模块
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Yi.Framework.CodeGun.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain.Entities
|
||||
{
|
||||
[SugarTable("YiField")]
|
||||
public class FieldEntity : Entity<Guid>
|
||||
{
|
||||
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true)]
|
||||
public override Guid Id { get; protected set; }
|
||||
/// <summary>
|
||||
/// 字段名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
|
||||
public int OrderNum { get; set; }
|
||||
public int Length { get; set; }
|
||||
|
||||
public FieldTypeEnum FieldType { get; set; }
|
||||
|
||||
public Guid TableId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否必填
|
||||
/// </summary>
|
||||
public bool IsRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否主键
|
||||
/// </summary>
|
||||
public bool IsKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否自增
|
||||
/// </summary>
|
||||
public bool IsAutoAdd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否公共
|
||||
/// </summary>
|
||||
public bool IsPublic { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain.Entities
|
||||
{
|
||||
[SugarTable("YiTable")]
|
||||
public class TableAggregateRoot : AggregateRoot<Guid>
|
||||
{
|
||||
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true)]
|
||||
public override Guid Id { get; protected set; }
|
||||
/// <summary>
|
||||
/// 表名
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 一表多字段
|
||||
/// </summary>
|
||||
[Navigate(NavigateType.OneToMany, nameof(FieldEntity.TableId))]
|
||||
public List<FieldEntity> Fields { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain.Entities
|
||||
{
|
||||
[SugarTable("YiTemplate")]
|
||||
public class TemplateEntity : Entity<Guid>
|
||||
{
|
||||
|
||||
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true)]
|
||||
public override Guid Id { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模板字符串
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString)]
|
||||
public string TemplateStr { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 生成路径
|
||||
/// </summary>
|
||||
public string BuildPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模板名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string? Remarks { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Yi.Framework.CodeGun.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain.Handlers
|
||||
{
|
||||
public class FieldTemplateHandler : TemplateHandlerBase, ITemplateHandler
|
||||
{
|
||||
public HandledTemplate Invoker(string str, string path)
|
||||
{
|
||||
var output = new HandledTemplate();
|
||||
output.TemplateStr = str.Replace("@field", BuildFields());
|
||||
output.BuildPath = path;
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 生成Fields
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string BuildFields()
|
||||
{
|
||||
StringBuilder fieldStrs = new StringBuilder();
|
||||
|
||||
|
||||
foreach (var field in Table.Fields)
|
||||
{
|
||||
var typeStr = typeof(FieldTypeEnum).GetFields().Where(x => x.Name == field.FieldType.ToString())?.FirstOrDefault().GetCustomAttribute<DisplayAttribute>().Name;
|
||||
|
||||
if (typeStr is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var nameStr = field.Name;
|
||||
|
||||
//添加备注
|
||||
if (!string.IsNullOrEmpty(field.Description))
|
||||
{
|
||||
var desStr = "/// <summary>\n" +
|
||||
$"///{field.Description}\n" +
|
||||
"/// </summary>\n";
|
||||
fieldStrs.AppendLine(desStr);
|
||||
}
|
||||
|
||||
//添加长度
|
||||
if (field.Length != 0)
|
||||
{
|
||||
var lengthStr = $"[SugarColumn(Length ={field.Length})]";
|
||||
fieldStrs.AppendLine(lengthStr);
|
||||
}
|
||||
|
||||
//添加可空类型
|
||||
string nullStr = "";
|
||||
if (field.IsRequired == false)
|
||||
{
|
||||
nullStr = "?";
|
||||
}
|
||||
|
||||
//添加字段
|
||||
var fieldStr = $"public {typeStr}{nullStr} {nameStr} {{ get; set; }}";
|
||||
|
||||
fieldStrs.AppendLine(fieldStr);
|
||||
}
|
||||
|
||||
return fieldStrs.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain.Handlers
|
||||
{
|
||||
public class HandledTemplate
|
||||
{
|
||||
public string TemplateStr { get; set; }
|
||||
|
||||
public string BuildPath { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Yi.Framework.CodeGun.Domain.Entities;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain.Handlers
|
||||
{
|
||||
public interface ITemplateHandler: ISingletonDependency
|
||||
{
|
||||
void SetTable(TableAggregateRoot table);
|
||||
HandledTemplate Invoker(string str, string path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Yi.Framework.CodeGun.Domain.Handlers
|
||||
{
|
||||
public class ModelTemplateHandler : TemplateHandlerBase, ITemplateHandler
|
||||
{
|
||||
public HandledTemplate Invoker(string str, string path)
|
||||
{
|
||||
var output = new HandledTemplate();
|
||||
output.TemplateStr = str.Replace("@model", char.ToLowerInvariant(Table.Name[0]) + Table.Name.Substring(1)).Replace("@Model", char.ToUpperInvariant(Table.Name[0]) + Table.Name.Substring(1));
|
||||
output.BuildPath = path.Replace("@model", char.ToLowerInvariant(Table.Name[0]) + Table.Name.Substring(1)).Replace("@Model", char.ToUpperInvariant(Table.Name[0]) + Table.Name.Substring(1));
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Yi.Framework.CodeGun.Domain.Handlers
|
||||
{
|
||||
public class NameSpaceTemplateHandler : TemplateHandlerBase, ITemplateHandler
|
||||
{
|
||||
public HandledTemplate Invoker(string str, string path)
|
||||
{
|
||||
var output = new HandledTemplate();
|
||||
output.TemplateStr = str.Replace("@namespace", "");
|
||||
output.BuildPath = path;
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Yi.Framework.CodeGun.Domain.Entities;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain.Handlers
|
||||
{
|
||||
public class TemplateHandlerBase
|
||||
{
|
||||
protected TableAggregateRoot Table { get; set; }
|
||||
|
||||
public void SetTable(TableAggregateRoot table)
|
||||
{
|
||||
Table = table;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using Volo.Abp.Domain.Services;
|
||||
using Yi.Framework.CodeGun.Domain.Entities;
|
||||
using Yi.Framework.CodeGun.Domain.Handlers;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain.Managers
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码文件领域服务,与代码文件生成相关,web to code
|
||||
/// </summary>
|
||||
public class CodeFileManager : DomainService
|
||||
{
|
||||
private IEnumerable<ITemplateHandler> _templateHandlers;
|
||||
private ISqlSugarRepository<TemplateEntity> _repository;
|
||||
private ISqlSugarRepository<FieldEntity> _fieldRepository;
|
||||
public CodeFileManager(IEnumerable<ITemplateHandler> templateHandlers, ISqlSugarRepository<FieldEntity> fieldRepository, ISqlSugarRepository<TemplateEntity> repository)
|
||||
{
|
||||
_templateHandlers = templateHandlers;
|
||||
_repository = repository;
|
||||
_fieldRepository = fieldRepository;
|
||||
}
|
||||
public async Task BuildWebToCodeAsync(TableAggregateRoot tableEntity)
|
||||
{
|
||||
var templates = await _repository.GetListAsync();
|
||||
foreach (var template in templates)
|
||||
{
|
||||
var handledTempalte = new HandledTemplate();
|
||||
handledTempalte.TemplateStr = template.TemplateStr;
|
||||
handledTempalte.BuildPath = template.BuildPath;
|
||||
foreach (var templateHandler in _templateHandlers)
|
||||
{
|
||||
templateHandler.SetTable(tableEntity);
|
||||
handledTempalte = templateHandler.Invoker(handledTempalte.TemplateStr, handledTempalte.BuildPath);
|
||||
}
|
||||
await BuildToFileAsync(handledTempalte);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task BuildToFileAsync(HandledTemplate handledTemplate)
|
||||
{
|
||||
if (!Directory.Exists(Path.GetDirectoryName(handledTemplate.BuildPath)))
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(handledTemplate.BuildPath));
|
||||
}
|
||||
await File.WriteAllTextAsync(handledTemplate.BuildPath, handledTemplate.TemplateStr);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Volo.Abp.Domain.Services;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain.Managers
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据库领域服务,与数据库相关,同步到数据库,web to db ,code to db
|
||||
/// </summary>
|
||||
public class DataBaseManger : DomainService
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Reflection;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Domain.Services;
|
||||
using Yi.Framework.CodeGun.Domain.Entities;
|
||||
using Yi.Framework.CodeGun.Domain.Shared.Enums;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain.Managers
|
||||
{
|
||||
/// <summary>
|
||||
/// 与webfrist相关,同步到web,code to web
|
||||
/// </summary>
|
||||
public class WebTemplateManager : DomainService
|
||||
{
|
||||
private ISqlSugarRepository<TableAggregateRoot> _repository;
|
||||
private IModuleContainer _moduleContainer;
|
||||
public WebTemplateManager(ISqlSugarRepository<TableAggregateRoot> repository, IModuleContainer moduleContainer)
|
||||
{
|
||||
_repository = repository;
|
||||
_moduleContainer= moduleContainer;
|
||||
}
|
||||
/// <summary>
|
||||
/// 通过当前的实体代码获取表存储
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
|
||||
public Task<List<TableAggregateRoot>> BuildCodeToWebAsync()
|
||||
{
|
||||
List<Type> entityTypes = new List<Type>();
|
||||
foreach (var module in _moduleContainer.Modules)
|
||||
{
|
||||
entityTypes.AddRange(module.Assembly.GetTypes()
|
||||
.Where(x => x.GetCustomAttribute<IgnoreCodeFirstAttribute>() == null)
|
||||
.Where(x => x.GetCustomAttribute<SugarTable>() != null)
|
||||
.Where(x => x.GetCustomAttribute<SplitTableAttribute>() is null));
|
||||
}
|
||||
|
||||
var tableAggregateRoots = new List<TableAggregateRoot>();
|
||||
foreach (var entityType in entityTypes)
|
||||
{
|
||||
tableAggregateRoots.Add(EntityTypeMapperToTable(entityType));
|
||||
}
|
||||
|
||||
return Task.FromResult(tableAggregateRoots);
|
||||
}
|
||||
|
||||
private TableAggregateRoot EntityTypeMapperToTable(Type entityType)
|
||||
{
|
||||
var tableAggregateRoot = new TableAggregateRoot();
|
||||
tableAggregateRoot.Fields = new List<FieldEntity>();
|
||||
var table = entityType.GetCustomAttribute<SugarTable>();
|
||||
|
||||
tableAggregateRoot.Name = table.TableName;
|
||||
|
||||
foreach (var p in entityType.GetProperties())
|
||||
{
|
||||
tableAggregateRoot.Fields.Add(PropertyMapperToFiled(p));
|
||||
}
|
||||
tableAggregateRoot.Fields.ForEach(x => x.TableId = tableAggregateRoot.Id);
|
||||
return tableAggregateRoot;
|
||||
}
|
||||
|
||||
|
||||
private FieldEntity PropertyMapperToFiled(PropertyInfo propertyInfo)
|
||||
{
|
||||
var fieldEntity = new FieldEntity();
|
||||
fieldEntity.Name = propertyInfo.Name;
|
||||
|
||||
|
||||
//获取数据类型,包括可空类型
|
||||
Type? fieldType = null;
|
||||
// 如果字段类型是 Nullable<T> 泛型类型
|
||||
if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
Type nullableType = Nullable.GetUnderlyingType(propertyInfo.PropertyType)!;
|
||||
fieldType = nullableType;
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldType = propertyInfo.PropertyType;
|
||||
}
|
||||
|
||||
//判断类型
|
||||
var enumName = typeof(FieldTypeEnum).GetFields(BindingFlags.Static | BindingFlags.Public).Where(x => x.GetCustomAttribute<DisplayAttribute>()?.Description == fieldType.Name).FirstOrDefault()?.Name;
|
||||
if (enumName is null)
|
||||
{
|
||||
fieldEntity.FieldType = FieldTypeEnum.String;
|
||||
// App.GetRequiredService<ILogger<WebTemplateManager>>().LogError($"字段类型:{propertyInfo.PropertyType.Name},未定义");
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldEntity.FieldType = (FieldTypeEnum)Enum.Parse(typeof(FieldTypeEnum), enumName);
|
||||
}
|
||||
|
||||
//判断是否可空
|
||||
if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
fieldEntity.IsRequired = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldEntity.IsRequired = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//判断是否主键
|
||||
if (propertyInfo.GetCustomAttribute<SugarColumn>()?.IsPrimaryKey == true)
|
||||
{
|
||||
fieldEntity.IsKey = true;
|
||||
}
|
||||
|
||||
//判断长度
|
||||
var colum = propertyInfo.GetCustomAttribute<SugarColumn>();
|
||||
if (colum is not null && colum.Length != 0)
|
||||
{
|
||||
fieldEntity.Length = colum.Length;
|
||||
}
|
||||
return fieldEntity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\common.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
|
||||
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="8.0.0" />
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\framework\Yi.Framework.SqlSugarCore.Abstractions\Yi.Framework.SqlSugarCore.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\Yi.Framework.CodeGun.Domain.Shared\Yi.Framework.CodeGun.Domain.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,15 @@
|
||||
using Volo.Abp.Domain;
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Framework.CodeGun.Domain.Shared;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.CodeGun.Domain
|
||||
{
|
||||
[DependsOn(typeof(YiFrameworkCodeGunDomainSharedModule),
|
||||
typeof(AbpDddDomainModule),
|
||||
typeof(YiFrameworkSqlSugarCoreAbstractionsModule))]
|
||||
public class YiFrameworkCodeGunDomainModule : AbpModule
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user