代码拉取完成,页面将自动刷新
// -----------------------------------------------------------------------------
// 园丁,是个很简单的管理系统
// gitee:https://gitee.com/hgflydream/Gardener
// issues:https://gitee.com/hgflydream/Gardener/issues
// -----------------------------------------------------------------------------
using Furion;
using Furion.DatabaseAccessor;
using Gardener.Core.CodeGeneration.Dtos;
using Gardener.Core.CodeGeneration.Services;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.ComponentModel.DataAnnotations;
using Gardener.Core.Util.Extensions;
using Gardener.Core.Attributes;
using Furion.FriendlyException;
using Gardener.Core.CodeGeneration.Resources;
using Furion.ViewEngine;
using System.Reflection;
using Gardener.Core.Dtos.Constraints;
namespace Gardener.Core.CodeGeneration.Impl.Services
{
/// <summary>
/// 代码生成服务
/// </summary>
[ApiDescriptionSettings(groups: "CodeGeneration", Module = "code-gen")]
public class CodeGenerationService : ICodeGenerationService
{
private readonly IEntityConfigService _entityConfigService;
private readonly IFieldConfigService _fieldConfigService;
private readonly IViewEngine _viewEngine;
private static IEnumerable<EntityDescriptionDto>? entityDescriptionsCache = null;
/// <summary>
/// 代码生成服务
/// </summary>
/// <param name="entityConfigService"></param>
/// <param name="viewEngine"></param>
/// <param name="fieldConfigService"></param>
public CodeGenerationService(IEntityConfigService entityConfigService, IViewEngine viewEngine, IFieldConfigService fieldConfigService)
{
_entityConfigService = entityConfigService;
_viewEngine = viewEngine;
_fieldConfigService = fieldConfigService;
}
/// <summary>
/// 生成代码
/// </summary>
/// <remarks>
/// 根据模板和实体类信息生成代码
/// </remarks>
/// <param name="generateCodeInput"></param>
/// <returns></returns>
public async Task<string> GenerationCode(GenerateCodeInput generateCodeInput)
{
var entityDescriptions = await GetEntityDescriptions();
var entityDescription = entityDescriptions.FirstOrDefault(x => x.EntityTypeFullName.Equals(generateCodeInput.EntityTypeFullName));
if (entityDescription == null)
{
throw Oops.BahLocalFrom<CodeGenLocalResource>(nameof(CodeGenLocalResource.EntityTypeIsNotFind), generateCodeInput.EntityTypeFullName);
}
//配置
try
{
string code = await _viewEngine.RunCompileAsync(generateCodeInput.TemplateContent, entityDescription, builderAction: builder =>
{
builder.AddAssemblyReferenceByName("System");
builder.AddAssemblyReferenceByName("Gardener.Core");
builder.AddAssemblyReferenceByName("Gardener.Core.Util");
builder.AddAssemblyReferenceByName("Gardener.Core.Shared");
builder.AddUsing("System");
builder.AddUsing("Gardener.Core");
builder.AddUsing("Gardener.Core.Resources");
builder.AddUsing("Gardener.Core.Enums");
builder.AddUsing("Gardener.Core.Attributes");
builder.AddUsing("Gardener.Core.Dtos");
builder.AddUsing("Gardener.Core.Util");
builder.AddUsing("Gardener.Core.Util.Extensions");
});
return code;
}
catch (Exception ex)
{
return ex.ToString();
}
}
/// <summary>
/// 获取实体描述列表
/// </summary>
/// <remarks>
/// 获取所有实体描述列表
/// </remarks>
/// <returns></returns>
public async Task<IEnumerable<EntityDescriptionDto>> GetEntityDescriptions()
{
if (entityDescriptionsCache == null)
{
entityDescriptionsCache = Scan();
}
IEnumerable<EntityDescriptionDto> Scan()
{
List<Type> entityTypes = new List<Type>();
foreach (var item in App.Assemblies)
{
var types = item.GetTypes();
foreach (var type in types)
{
if (!type.IsAssignableTo(typeof(IPrivateEntity)) || type.IsAbstract) continue;
entityTypes.Add(type);
}
}
List<EntityDescriptionDto> result = new List<EntityDescriptionDto>();
foreach (var item in entityTypes)
{
List<FieldDescriptionDto> fields = GetFieldDescriptions(item);
DisplayAttribute? displayAttribute = item.GetAttribute<DisplayAttribute>();
string entityDtoName = item.Name + "Dto";
string? baseTypeName = item.BaseType?.Name;
if (baseTypeName != null && !baseTypeName.Contains("EntityBase"))
{
entityDtoName = baseTypeName;
}
var entityDesc = new EntityDescriptionDto()
{
EntityType = item,
EntityDtoName = entityDtoName,
EntityTypeName = item.Name,
EntityTypeFullName = item.FullName ?? "",
NameSpace = item.Namespace ?? "",
AssemblyName = item.Assembly.ManifestModule.Name ?? "",
ImplementIModelCreated = item.IsAssignableTo(typeof(IModelCreated)),
ImplementIModelLocked = item.IsAssignableTo(typeof(IModelLocked)),
ImplementIModelDeleted = item.IsAssignableTo(typeof(IModelDeleted)),
ImplementIModelUpdated = item.IsAssignableTo(typeof(IModelUpdated)),
ImplementIModelTenant = item.IsAssignableTo(typeof(IModelTenant)),
ImplementIModelTenantId = item.IsAssignableTo(typeof(IModelTenantId)),
ImplementIModelModule = item.IsAssignableTo(typeof(IModelModule)),
Fields = fields,
DisplayName = displayAttribute?.GetName(),
DisplayNameResourceTypeName = displayAttribute?.ResourceType?.Name,
DisplayNameResourceType = displayAttribute?.ResourceType
};
var primaryKey = fields.FirstOrDefault(x => x.IsPrimaryKey);
if (primaryKey != null)
{
Type genericType = typeof(IModelId<>);
Type[] typeArguments = new Type[] { primaryKey.Type };
Type constructedType = genericType.MakeGenericType(typeArguments);
entityDesc.ImplementIModelId = item.IsAssignableTo(constructedType);
entityDesc.PrimaryKeyName = primaryKey.Name;
entityDesc.PrimaryKeyTypeName = primaryKey.TypeName;
}
result.Add(entityDesc);
}
return result;
}
var configs = await _entityConfigService.GetAll();
var fieldConfigs = await _fieldConfigService.GetAll();
foreach (var entityDesc in entityDescriptionsCache)
{
var entityConfig = configs.FirstOrDefault(x => x.Id.Equals(entityDesc.EntityTypeFullName));
if (entityConfig == null)
{
string baseNameSpace = entityDesc.AssemblyName.Replace(".Api.", ".").Replace(".Impl", "").Replace(".Entities", "").Replace(".dll", "");
entityConfig = new EntityConfigDto()
{
Id = entityDesc.EntityTypeFullName,
BaseNameSpace = baseNameSpace,
ApiNameSpace = baseNameSpace + ".Impl",
ClientNameSpace = baseNameSpace + ".Client",
MenuName = entityDesc.DisplayName,
EnableAdd = true,
EnableDelete = true,
EnableUpdate = true,
EnableDeleteSelected = true,
EnableDetail = true,
EnableLock = true,
EnableRefresh = true,
EnableSearch = true,
UseTreeList = false,
};
}
entityDesc.EntityConfig = entityConfig;
int minOrder = 100;
int orderStep = 10;
int orderIndex = 0;
entityDesc.Fields.ForEach(x =>
{
x.FieldConfig.ListOrder = minOrder + (orderIndex * orderStep);
orderIndex++;
if (!x.IsPrimaryKey
&& !x.Name.Equals(nameof(IModelDeleted.IsDeleted))
&& !x.Name.Equals(nameof(IModelCreated.CreatedTime))
&& !x.Name.Equals(nameof(IModelCreated.CreateIdentityType))
&& !x.Name.Equals(nameof(IModelCreated.CreateBy))
&& !x.Name.Equals(nameof(IModelUpdated.UpdatedTime))
&& !x.Name.Equals(nameof(IModelUpdated.UpdateIdentityType))
&& !x.Name.Equals(nameof(IModelUpdated.UpdateBy))
&& !x.Name.Equals(nameof(IModelTenantPermission.EmpowerAllTenants))
)
{
x.FieldConfig.CanModity = true;
}
if (x.Name.Equals(nameof(IModelDeleted.IsDeleted)) ||
x.Name.Equals(nameof(IModelUpdated.UpdateBy)) ||
x.Name.Equals(nameof(IModelUpdated.UpdateIdentityType)) ||
x.Name.Equals(nameof(IModelTenantPermission.EmpowerAllTenants)) ||
x.Name.Equals(nameof(IModelCreated.CreateBy)) ||
x.Name.Equals(nameof(IModelCreated.CreateIdentityType)))
{
x.FieldConfig.ShowInList = false;
x.FieldConfig.ShowInDetail = false;
x.FieldConfig.ListOrder = minOrder + 10000;
}
else if (x.Name.Equals(nameof(IModelId<int>.Id)))
{
x.FieldConfig.ListOrder = 0;
}
else if (x.Name.Equals(nameof(IModelTenantId.TenantId)))
{
x.FieldConfig.ListOrder = 1;
}
else if (x.Name.Equals(nameof(IModelLocked.IsLocked)))
{
x.FieldConfig.ListOrder = 2000;
}
else if (x.Name.Equals(nameof(IModelCreated.CreatedTime)))
{
x.FieldConfig.Sortable = true;
x.FieldConfig.DefaultSortOrder = "desc";
x.FieldConfig.ListOrder = 2010;
}
else if (x.Name.Equals(nameof(IModelUpdated.UpdatedTime)))
{
x.FieldConfig.ListOrder = 2020;
}
x.FieldConfig.DetailOrder = x.FieldConfig.ListOrder;
var fieldConfig = fieldConfigs.FirstOrDefault(y => y.EntityTypeFullName.Equals(entityDesc.EntityTypeFullName) && y.FieldName.Equals(x.Name));
if (fieldConfig != null)
{
x.FieldConfig = fieldConfig;
}
});
}
return entityDescriptionsCache;
}
/// <summary>
/// 获取字段描述信息
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private List<FieldDescriptionDto> GetFieldDescriptions(Type type)
{
List<FieldDescriptionDto> fields = new List<FieldDescriptionDto>();
var ps = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var p in ps)
{
Type pType = p.PropertyType;
bool isNullableType = pType.IsNullableType();
if (isNullableType)
{
pType = pType.GetUnNullableType();
}
if (!pType.IsSystemType())
{
continue;
}
//字符串类型获取类型不包含Nullable信息
int? maxLength = null;
int? minLength = null;
if (pType.Equals(typeof(String)))
{
isNullableType = !p.HasAttribute<RequiredAttribute>();
maxLength = p.GetAttribute<MaxLengthAttribute>()?.Length;
minLength = p.GetAttribute<MinLengthAttribute>()?.Length;
}
bool isEnum = pType.IsEnum;
var fd = new FieldDescriptionDto(type.FullName ?? type.Name, p.Name, pType.Name);
fd.Type = pType;
fd.IsNullableType = isNullableType;
fd.IsEnum = isEnum;
fd.IsPrimaryKey = p.HasAttribute<KeyAttribute>();
fd.Order = p.GetAttribute<OrderAttribute>()?.Order;
fd.DictCodeTypeValue = p.GetAttribute<CodeTypeAttribute>()?.CodeTypeValue;
if (fd.DictCodeTypeValue != null)
{
fd.IsDictCodeField = true;
}
fd.MaxLength = maxLength;
fd.MinLength = minLength;
fields.Add(fd);
}
return fields;
}
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。