移动系统liao
2024-08-14 7622668170f8341cd98e9a32d559f0073cedcc95
no message
41个文件已添加
3114 ■■■■■ 已修改文件
.gitignore 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Application/GlobalUsings.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Application/System/Dtos/Mapper.cs 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Application/System/Services/ISystemService.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Application/System/Services/SystemService.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Application/System/SystemAppService.cs 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Application/applicationsettings.json 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Application/cylsg.Application.csproj 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Application/cylsg.Application.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Core/Attributes/CoderFirstAttribute.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Core/BaseModelBase.cs 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Core/BaseRepository.cs 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Core/DbContext.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Core/DbCoreUntil.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Core/cylsg.Core.csproj 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Core/cylsg.Core.xml 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Model/UserModel/User.cs 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Model/cylsg.Model.csproj 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Core/Handlers/JwtHandler.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Core/Startup.cs 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Core/cylsg.Web.Core.csproj 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Core/cylsg.Web.Core.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/Controllers/HomeController.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/Program.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/Properties/launchSettings.json 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/SingleFilePublish.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/Views/Home/Index.cshtml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/Views/Shared/_Layout.cshtml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/Views/_ViewImports.cshtml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/Views/_ViewStart.cshtml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/appsettings.Development.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/appsettings.json 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/cylsg.Web.Entry.csproj 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/cylsg.Web.Entry.csproj.user 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.Web.Entry/wwwroot/images/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.sln 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.utility/CommonHelper.cs 850 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.utility/Extend/EmunEx.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.utility/Extend/StringEx.cs 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.utility/Extend/TypeAndExpressionEx.cs 1021 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cylsg/cylsg.utility/cylsg.utility.csproj 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
New file
@@ -0,0 +1,14 @@
cylsg/.vs/
cylsg/cylsg.Application/bin/
cylsg/cylsg.Application/obj/
cylsg/cylsg.Core/bin/
cylsg/cylsg.Core/obj/
cylsg/cylsg.Model/bin/Debug/net8.0/cylsg.Core.dll
cylsg/cylsg.Model/bin/
cylsg/cylsg.Model/obj/
cylsg/cylsg.utility/bin/
cylsg/cylsg.utility/obj/
cylsg/cylsg.Web.Core/bin/
cylsg/cylsg.Web.Core/obj/
cylsg/cylsg.Web.Entry/bin/
cylsg/cylsg.Web.Entry/obj/
cylsg/cylsg.Application/GlobalUsings.cs
New file
@@ -0,0 +1,15 @@
global using Furion;
global using Furion.DataEncryption;
global using Furion.DataValidation;
global using Furion.DependencyInjection;
global using Furion.DynamicApiController;
global using Furion.Extensions;
global using Furion.FriendlyException;
global using Furion.Logging;
global using Mapster;
global using Microsoft.AspNetCore.Authorization;
global using Microsoft.AspNetCore.Http;
global using Microsoft.AspNetCore.Mvc;
global using Microsoft.CodeAnalysis;
global using System.ComponentModel.DataAnnotations;
global using SqlSugar;
cylsg/cylsg.Application/System/Dtos/Mapper.cs
New file
@@ -0,0 +1,8 @@
namespace cylsg.Application;
public class Mapper : IRegister
{
    public void Register(TypeAdapterConfig config)
    {
    }
}
cylsg/cylsg.Application/System/Services/ISystemService.cs
New file
@@ -0,0 +1,6 @@
namespace cylsg.Application;
public interface ISystemService
{
    string GetDescription();
}
cylsg/cylsg.Application/System/Services/SystemService.cs
New file
@@ -0,0 +1,9 @@
namespace cylsg.Application;
public class SystemService : ISystemService, ITransient
{
    public string GetDescription()
    {
        return "让 .NET 开发更简单,更通用,更流行。";
    }
}
cylsg/cylsg.Application/System/SystemAppService.cs
New file
@@ -0,0 +1,47 @@
using cylsg.Core.Attributes;
using cylsg.Core;
namespace cylsg.Application;
/// <summary>
/// 系统服务接口
/// </summary>
public class SystemAppService : IDynamicApiController
{
    private readonly ISystemService _systemService;
    private ISqlSugarClient _sqlSugarClient;
    public SystemAppService(ISystemService systemService,ISqlSugarClient sqlSugarClient)
    {
        _systemService = systemService;
        _sqlSugarClient = sqlSugarClient;
    }
    /// <summary>
    /// 创建系统
    /// </summary>
    /// <returns></returns>
    public string codefirst()
    {
            try
            {
                //_ez.GetDb().AsTenant().ChangeDatabase(ConfigId);
                _sqlSugarClient.DbMaintenance.CreateDatabase();
                Type[]? types = DbCoreUntil.DbCodeFirstModes("cylsg.Model", thisAttribute: typeof(CoderFirstAttribute));
                _sqlSugarClient.CodeFirst.SetStringDefaultLength(512).InitTables(types ?? new Type[] { });
                return "创建成功";
            }
            catch (Exception e)
            {
                return $"创建失败,报错: {e.Message},-----详情:{e.StackTrace}";
            }
    }
}
cylsg/cylsg.Application/applicationsettings.json
New file
@@ -0,0 +1,31 @@
{
  "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
  "SpecificationDocumentSettings": {
    "DocumentTitle": "Furion | 规范化接口",
    "GroupOpenApiInfos": [
      {
        "Group": "Default",
        "Title": "规范化演示",
        "Description": "川印灵时工",
        "Version": "1.0.0",
        "Contact": {
          "Name": "",
          "Email": "monksoul@outlook.com"
        },
        "License": {
          "Name": "Apache-2.0"
        }
      }
    ]
  },
  "CorsAccessorSettings": {
    "WithExposedHeaders": [
      "access-token",
      "x-access-token",
      "environment"
    ]
  }
}
cylsg/cylsg.Application/cylsg.Application.csproj
New file
@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <NoWarn>1701;1702;1591</NoWarn>
        <DocumentationFile>cylsg.Application.xml</DocumentationFile>
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>
    <ItemGroup>
        <None Remove="applicationsettings.json" />
        <None Remove="cylsg.Application.xml" />
    </ItemGroup>
    <ItemGroup>
        <Content Include="applicationsettings.json">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </Content>
    </ItemGroup>
    <ItemGroup>
        <ProjectReference Include="..\cylsg.Core\cylsg.Core.csproj" />
        <ProjectReference Include="..\cylsg.Model\cylsg.Model.csproj" />
    </ItemGroup>
    <ItemGroup>
        <Folder Include="System\Services\" />
    </ItemGroup>
</Project>
cylsg/cylsg.Application/cylsg.Application.xml
New file
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<doc>
    <assembly>
        <name>cylsg.Application</name>
    </assembly>
    <members>
        <member name="T:cylsg.Application.SystemAppService">
            <summary>
            系统服务接口
            </summary>
        </member>
        <member name="M:cylsg.Application.SystemAppService.codefirst">
            <summary>
            创建系统
            </summary>
            <returns></returns>
        </member>
    </members>
</doc>
cylsg/cylsg.Core/Attributes/CoderFirstAttribute.cs
New file
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cylsg.Core.Attributes
{
    /// <summary>
    /// /标记是否是codefirst
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class CoderFirstAttribute : Attribute
    {
    }
}
cylsg/cylsg.Core/BaseModelBase.cs
New file
@@ -0,0 +1,86 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cylsg.Core
{
    /// <summary>
    /// 最基础的模型,创建时间创建人记录
    /// </summary>
    public class BaseModelBase
    {
        /// <summary>
        /// 创建时间
        /// </summary>
        [Display(Name = "创建时间 ")]
        [SugarColumn(ColumnDescription = "创建时间 ")]
        public DateTime? CreateTime { get; set; }
        /// <summary>
        /// 创建人
        /// </summary>
        [Display(Name = "创建人 ")]
        [SugarColumn(ColumnDescription = "创建人 ", Length = 100)]
        public string CreateBy { get; set; }
        /// <summary>
        /// 修改时间
        /// </summary>
        [Display(Name = "修改时间 ")]
        [SugarColumn(ColumnDescription = "修改时间 ")]
        public DateTime? UpDataTime { get; set; }
        /// <summary>
        /// 修改人
        /// </summary>
        [Display(Name = "修改人 ")]
        [SugarColumn(ColumnDescription = "修改人 ", Length = 100)]
        public string UpDataBy { get; set; }
    }
    /// <summary>
    /// 修正基础模型,包括了删除标志,生效标志,排序,和使能
    /// </summary>
    public class BaseModel : BaseModelBase
    {
        /// <summary>
        /// 是否删除
        /// </summary>
        [Display(Name = "是否删除 ")]
        [SugarColumn(ColumnDescription = "是否删除 ", DefaultValue = "0")]
        public bool IsDeleted { get; set; } = false;
        /// <summary>
        /// 是否有效
        /// </summary>
        [Display(Name = "是否有效 ")]
        [SugarColumn(ColumnDescription = "是否有效 ", DefaultValue = "1")]
        public bool IsEn { get; set; } = true;
        /// <summary>
        /// 排序
        /// </summary>
        [Display(Name = "排序 ")]
        [SugarColumn(ColumnDescription = "排序 ", IsNullable = true)]
        public int? Sort { get; set; }
        /// <summary>
        /// 标注
        /// </summary>
        [Display(Name = "标注 ")]
        [SugarColumn(ColumnDescription = "标注 ", IsNullable = true)]
        public string Remake { get; set; }
        /// <summary>
        /// 租户
        /// </summary>
        [Display(Name = "租户 ")]
        [SugarColumn(ColumnDescription = "租户 扩展 ", IsNullable = true)]
        public int? TenantID { get; set; }
    }
}
cylsg/cylsg.Core/BaseRepository.cs
New file
@@ -0,0 +1,98 @@
using Furion;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace cylsg.Core
{
    /// <summary>
    /// 仓储类,使用方式只需要继承就行
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseRepository<T> : SimpleClient<T> where T : class, new()
    {
        public BaseRepository(ISqlSugarClient context = null) : base(context)//默认值等于null不能少
        {
            base.Context = App.GetService<ISqlSugarClient>();//用手动获取方式支持切换仓储
        }
        /// <summary>
        /// 重写更新方法
        /// </summary>
        /// <param name="updateObj"></param>
        /// <returns></returns>
        public Task<bool> EzUpdateAsync(T updateObj)
        {
            var intbs = updateObj as BaseModelBase;
            if (intbs != null)
            {
                intbs.UpDataBy = GetJwtBy();
                intbs.UpDataTime = DateTime.Now;
            }
            return base.UpdateAsync(updateObj);
        }
        /// <summary>
        /// 异步插入
        /// </summary>
        /// <param name="insertObj"></param>
        /// <returns></returns>
        public Task<bool> EzInsertAsync(T insertObj)
        {
            var intbs = insertObj as BaseModelBase;
            if (intbs != null)
            {
                intbs.CreateBy = GetJwtBy();
                intbs.CreateTime = DateTime.Now;
            }
            return base.InsertAsync(insertObj);
        }
        /// <summary>
        /// 重写插入
        /// </summary>
        /// <param name="insertObj"></param>
        /// <returns></returns>
        public T EzInsertReturnEntity(T insertObj)
        {
            var intbs = insertObj as BaseModelBase;
            if (intbs != null)
            {
                intbs.CreateBy = GetJwtBy();
                intbs.CreateTime = DateTime.Now;
            }
            return base.InsertReturnEntity(insertObj);
        }
        /// <summary>
        /// 异步插入
        /// </summary>
        /// <param name="insertObj"></param>
        /// <returns></returns>
        public Task<int> EzInsertReturnIdentityAsync(T insertObj)
        {
            var intbs = insertObj as BaseModelBase;
            if (intbs != null)
            {
                intbs.CreateBy = GetJwtBy();
                intbs.CreateTime = DateTime.Now;
            }
            return base.InsertReturnIdentityAsync(insertObj);
        }
        /// <summary>
        /// 获取用户姓名和ID
        /// </summary>
        /// <returns></returns>
        private string GetJwtBy()
        {
            return (App.User?.FindFirstValue("UserID") ?? "") + "|" + (App.User?.FindFirstValue("NickName") ?? "系统自主处理");
        }
    }
    }
cylsg/cylsg.Core/DbContext.cs
New file
@@ -0,0 +1,22 @@
using Furion;
using SqlSugar;
using System.Collections.Generic;
namespace cylsg.Core;
/// <summary>
/// 数据库上下文对象
/// </summary>
public static class DbContext
{
    /// <summary>
    /// SqlSugar 数据库实例
    /// </summary>
    public static readonly SqlSugarScope Instance = new(
        // 读取 appsettings.json 中的 ConnectionConfigs 配置节点
        App.GetConfig<List<ConnectionConfig>>("ConnectionConfigs")
        , db =>
        {
            // 这里配置全局事件,比如拦截执行 SQL
        });
}
cylsg/cylsg.Core/DbCoreUntil.cs
New file
@@ -0,0 +1,34 @@
using cylsg.utility;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cylsg.Core
{
    public class DbCoreUntil
    {
        /// 获取需要更新或者是创建的 数据库表模型List
        /// </summary>
        /// <typeparam name="T">继承表某个表的所有</typeparam>
        /// <param name="ModeProjectName"></param>
        /// <param name="ModeNamespace"></param>
        /// <param name="ConfigId"></param>
        /// <returns></returns>
        public static Type[] DbCodeFirstModes(string ModeProjectName, string ModeNamespace = null, string ConfigId = null, Type subClass = null, Type thisAttribute = null)
        {
#nullable enable
            Type[]? types = CommonHelper.GetAllAssembly().Where(x => x.FullName.Contains(ModeProjectName + ",")).FirstOrDefault()?.GetTypes().WhereIF(!string.IsNullOrEmpty(ModeNamespace), name => name.FullName.Contains(ModeNamespace + ".")).ToArray()
                .WhereIF(subClass != null, x => x.IsSubclassOf(subClass)).ToArray()
                .WhereIF(thisAttribute != null, x => x.GetCustomAttributes(thisAttribute, true).Length > 0).ToArray();
            return types;
        }
    }
}
cylsg/cylsg.Core/cylsg.Core.csproj
New file
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <NoWarn>1701;1702;1591</NoWarn>
        <DocumentationFile>cylsg.Core.xml</DocumentationFile>
    </PropertyGroup>
    <ItemGroup>
        <None Remove="cylsg.Core.xml" />
    </ItemGroup>
    <ItemGroup>
        <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.5.3" />
        <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.5.3" />
        <PackageReference Include="Furion.Pure" Version="4.9.5.3" />
        <PackageReference Include="SqlSugarCore" Version="5.1.4.166" />
    </ItemGroup>
    <ItemGroup>
      <ProjectReference Include="..\cylsg.utility\cylsg.utility.csproj" />
    </ItemGroup>
</Project>
cylsg/cylsg.Core/cylsg.Core.xml
New file
@@ -0,0 +1,119 @@
<?xml version="1.0"?>
<doc>
    <assembly>
        <name>cylsg.Core</name>
    </assembly>
    <members>
        <member name="T:cylsg.Core.Attributes.CoderFirstAttribute">
            <summary>
            /标记是否是codefirst
            </summary>
        </member>
        <member name="T:cylsg.Core.BaseModelBase">
            <summary>
            最基础的模型,创建时间创建人记录
            </summary>
        </member>
        <member name="P:cylsg.Core.BaseModelBase.CreateTime">
            <summary>
            创建时间
            </summary>
        </member>
        <member name="P:cylsg.Core.BaseModelBase.CreateBy">
            <summary>
            创建人
            </summary>
        </member>
        <member name="P:cylsg.Core.BaseModelBase.UpDataTime">
            <summary>
            修改时间
            </summary>
        </member>
        <member name="P:cylsg.Core.BaseModelBase.UpDataBy">
            <summary>
            修改人
            </summary>
        </member>
        <member name="T:cylsg.Core.BaseModel">
            <summary>
            修正基础模型,包括了删除标志,生效标志,排序,和使能
            </summary>
        </member>
        <member name="P:cylsg.Core.BaseModel.IsDeleted">
            <summary>
            是否删除
            </summary>
        </member>
        <member name="P:cylsg.Core.BaseModel.IsEn">
            <summary>
            是否有效
            </summary>
        </member>
        <member name="P:cylsg.Core.BaseModel.Sort">
            <summary>
            排序
            </summary>
        </member>
        <member name="P:cylsg.Core.BaseModel.Remake">
            <summary>
            标注
            </summary>
        </member>
        <member name="P:cylsg.Core.BaseModel.TenantID">
            <summary>
            租户
            </summary>
        </member>
        <member name="T:cylsg.Core.BaseRepository`1">
            <summary>
            仓储类,使用方式只需要继承就行
            </summary>
            <typeparam name="T"></typeparam>
        </member>
        <member name="M:cylsg.Core.BaseRepository`1.EzUpdateAsync(`0)">
            <summary>
            重写更新方法
            </summary>
            <param name="updateObj"></param>
            <returns></returns>
        </member>
        <member name="M:cylsg.Core.BaseRepository`1.EzInsertAsync(`0)">
            <summary>
            异步插入
            </summary>
            <param name="insertObj"></param>
            <returns></returns>
        </member>
        <member name="M:cylsg.Core.BaseRepository`1.EzInsertReturnEntity(`0)">
            <summary>
            重写插入
            </summary>
            <param name="insertObj"></param>
            <returns></returns>
        </member>
        <member name="M:cylsg.Core.BaseRepository`1.EzInsertReturnIdentityAsync(`0)">
            <summary>
            异步插入
            </summary>
            <param name="insertObj"></param>
            <returns></returns>
        </member>
        <member name="M:cylsg.Core.BaseRepository`1.GetJwtBy">
            <summary>
            获取用户姓名和ID
            </summary>
            <returns></returns>
        </member>
        <member name="T:cylsg.Core.DbContext">
            <summary>
            数据库上下文对象
            </summary>
        </member>
        <member name="F:cylsg.Core.DbContext.Instance">
            <summary>
            SqlSugar 数据库实例
            </summary>
        </member>
        <!-- Badly formed XML comment ignored for member "M:cylsg.Core.DbCoreUntil.DbCodeFirstModes(System.String,System.String,System.String,System.Type,System.Type)" -->
    </members>
</doc>
cylsg/cylsg.Model/UserModel/User.cs
New file
@@ -0,0 +1,62 @@
using cylsg.Core;
using cylsg.Core.Attributes;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cylsg.Model.UserModel
{
    /// <summary>
    /// 用户模型
    /// </summary>
    [Description("用户模型")]
    [CoderFirst]
    public class User:BaseModelBase
    {
        /// <summary>
        /// 用户Id
        /// </summary>
        [SugarColumn(ColumnDescription = "用户ID", IsPrimaryKey = true, IsIdentity = true)]
        public int Id { get; set; }
        /// <summary>
        /// 电话
        /// </summary>
        [SugarColumn(ColumnDescription = "电话")]
        public string Phone { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        [SugarColumn(ColumnDescription = "名称",Length =100)]
        public string name { get; set; }
        /// <summary>
        /// 电话号码
        /// </summary>
        [SugarColumn(ColumnDescription = "电话号码", Length = 30)]
        public string ItCode { get; set; }
        /// <summary>
        /// 昵称
        /// </summary>
        [SugarColumn(ColumnDescription = "用户ID", Length = 100)]
        public int Nickname { get; set; }
        /// <summary>
        /// 密码
        /// </summary>
        [SugarColumn(ColumnDescription = "密码", Length = 100)]
        public int PassWord { get; set; }
        /// <summary>
        /// 头像地址
        /// </summary>
        [SugarColumn(ColumnDescription = "头像地址")]
        public int Avatar { get; set; }
    }
}
cylsg/cylsg.Model/cylsg.Model.csproj
New file
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <GenerateDocumentationFile>True</GenerateDocumentationFile>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\cylsg.Core\cylsg.Core.csproj" />
  </ItemGroup>
</Project>
cylsg/cylsg.Web.Core/Handlers/JwtHandler.cs
New file
@@ -0,0 +1,16 @@
using Furion.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
namespace cylsg.Web.Core;
public class JwtHandler : AppAuthorizeHandler
{
    public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
    {
        // 这里写您的授权判断逻辑,授权通过返回 true,否则返回 false
        return Task.FromResult(true);
    }
}
cylsg/cylsg.Web.Core/Startup.cs
New file
@@ -0,0 +1,62 @@
using cylsg.Core;
using Furion;
using Furion.VirtualFileServer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SqlSugar;
namespace cylsg.Web.Core;
public class Startup : AppStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddConsoleFormatter();
        services.AddJwt<JwtHandler>();
        services.AddCorsAccessor();
        services.AddSingleton<ISqlSugarClient>(s =>
        {
            return DbContext.Instance;
        }
        );
            services.AddControllersWithViews()
                    .AddInjectWithUnifyResult();
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseCorsAccessor();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseInject();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}
cylsg/cylsg.Web.Core/cylsg.Web.Core.csproj
New file
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <NoWarn>1701;1702;1591</NoWarn>
        <DocumentationFile>cylsg.Web.Core.xml</DocumentationFile>
    </PropertyGroup>
    <ItemGroup>
        <None Remove="cylsg.Web.Core.xml" />
    </ItemGroup>
    <ItemGroup>
        <ProjectReference Include="..\cylsg.Application\cylsg.Application.csproj" />
    </ItemGroup>
</Project>
cylsg/cylsg.Web.Core/cylsg.Web.Core.xml
New file
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<doc>
    <assembly>
        <name>cylsg.Web.Core</name>
    </assembly>
    <members>
    </members>
</doc>
cylsg/cylsg.Web.Entry/Controllers/HomeController.cs
New file
@@ -0,0 +1,23 @@
using cylsg.Application;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace cylsg.Web.Entry.Controllers;
[AllowAnonymous]
public class HomeController : Controller
{
    private readonly ISystemService _systemService;
    public HomeController(ISystemService systemService)
    {
        _systemService = systemService;
    }
    public IActionResult Index()
    {
        ViewBag.Description = _systemService.GetDescription();
        return View();
    }
}
cylsg/cylsg.Web.Entry/Program.cs
New file
@@ -0,0 +1 @@
Serve.Run(RunOptions.Default.WithArgs(args));
cylsg/cylsg.Web.Entry/Properties/launchSettings.json
New file
@@ -0,0 +1,28 @@
{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:58595",
      "sslPort": 44326
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "cylsg.Web.Entry": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}
cylsg/cylsg.Web.Entry/SingleFilePublish.cs
New file
@@ -0,0 +1,22 @@
using Furion;
using System.Reflection;
namespace cylsg.Web.Entry;
public class SingleFilePublish : ISingleFilePublish
{
    public Assembly[] IncludeAssemblies()
    {
        return Array.Empty<Assembly>();
    }
    public string[] IncludeAssemblyNames()
    {
        return new[]
        {
            "cylsg.Application",
            "cylsg.Core",
            "cylsg.Web.Core"
        };
    }
}
cylsg/cylsg.Web.Entry/Views/Home/Index.cshtml
New file
@@ -0,0 +1,9 @@
@{
    ViewData["Title"] = ViewBag.Description;
}
<div style="text-align:center;margin-top:50px;">
    <p>@ViewBag.Description</p>
    <p><a href="/api">API 接口</a>
</div>
cylsg/cylsg.Web.Entry/Views/Shared/_Layout.cshtml
New file
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewData["Title"] - Furion</title>
</head>
<body>
    @RenderBody()
</body>
</html>
cylsg/cylsg.Web.Entry/Views/_ViewImports.cshtml
New file
@@ -0,0 +1,2 @@
@using cylsg.Web.Entry
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
cylsg/cylsg.Web.Entry/Views/_ViewStart.cshtml
New file
@@ -0,0 +1,3 @@
@{
    Layout = "_Layout";
}
cylsg/cylsg.Web.Entry/appsettings.Development.json
New file
@@ -0,0 +1,10 @@
{
  "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.EntityFrameworkCore": "Information"
    }
  }
}
cylsg/cylsg.Web.Entry/appsettings.json
New file
@@ -0,0 +1,23 @@
{
  "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.EntityFrameworkCore": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionConfigs": [
    {
      //"ConnectionString": "Data Source=./Furion.db",
      //"DbType": "Sqlite",
      //"IsAutoCloseConnection": true
        "ConnectionString": "Server=MS-FSEUTNLCXFDB\\SQLEXPRESS;Database=CyLsgDb; MultipleActiveResultSets=true;pooling=true;min pool size=5;max pool size=32767;connect timeout=20;Encrypt=True;TrustServerCertificate=True;integrated security=True;",
        "DbType": "SqlServer", // "SqlServer" ,mysql,
        "IsAutoCloseConnection": true
    }
  ]
}
cylsg/cylsg.Web.Entry/cylsg.Web.Entry.csproj
New file
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>
        <PublishReadyToRunComposite>true</PublishReadyToRunComposite>
    </PropertyGroup>
    <ItemGroup>
        <ProjectReference Include="..\cylsg.Web.Core\cylsg.Web.Core.csproj" />
    </ItemGroup>
</Project>
cylsg/cylsg.Web.Entry/cylsg.Web.Entry.csproj.user
New file
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
  </PropertyGroup>
  <PropertyGroup>
    <ActiveDebugProfile>cylsg.Web.Entry</ActiveDebugProfile>
  </PropertyGroup>
</Project>
cylsg/cylsg.Web.Entry/wwwroot/images/logo.png
cylsg/cylsg.sln
New file
@@ -0,0 +1,55 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32519.111
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cylsg.Application", "cylsg.Application\cylsg.Application.csproj", "{AB699EE9-43A8-46F2-A855-04A26DE63372}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cylsg.Web.Core", "cylsg.Web.Core\cylsg.Web.Core.csproj", "{9D14BB78-DA2A-4040-B9DB-5A515B599181}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cylsg.Core", "cylsg.Core\cylsg.Core.csproj", "{4FB30091-15C7-4FD9-AB7D-266814F360F5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cylsg.Web.Entry", "cylsg.Web.Entry\cylsg.Web.Entry.csproj", "{9826E365-EEE9-4721-A738-B02AB64D47E5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cylsg.Model", "cylsg.Model\cylsg.Model.csproj", "{09E3AFC0-0975-4842-891F-9B5C78E12458}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cylsg.utility", "cylsg.utility\cylsg.utility.csproj", "{5ED2C481-2D74-43BC-ABAF-1455A052FAA4}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
        Release|Any CPU = Release|Any CPU
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {AB699EE9-43A8-46F2-A855-04A26DE63372}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {AB699EE9-43A8-46F2-A855-04A26DE63372}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {AB699EE9-43A8-46F2-A855-04A26DE63372}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {AB699EE9-43A8-46F2-A855-04A26DE63372}.Release|Any CPU.Build.0 = Release|Any CPU
        {9D14BB78-DA2A-4040-B9DB-5A515B599181}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {9D14BB78-DA2A-4040-B9DB-5A515B599181}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {9D14BB78-DA2A-4040-B9DB-5A515B599181}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {9D14BB78-DA2A-4040-B9DB-5A515B599181}.Release|Any CPU.Build.0 = Release|Any CPU
        {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Release|Any CPU.Build.0 = Release|Any CPU
        {9826E365-EEE9-4721-A738-B02AB64D47E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {9826E365-EEE9-4721-A738-B02AB64D47E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {9826E365-EEE9-4721-A738-B02AB64D47E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {9826E365-EEE9-4721-A738-B02AB64D47E5}.Release|Any CPU.Build.0 = Release|Any CPU
        {09E3AFC0-0975-4842-891F-9B5C78E12458}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {09E3AFC0-0975-4842-891F-9B5C78E12458}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {09E3AFC0-0975-4842-891F-9B5C78E12458}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {09E3AFC0-0975-4842-891F-9B5C78E12458}.Release|Any CPU.Build.0 = Release|Any CPU
        {5ED2C481-2D74-43BC-ABAF-1455A052FAA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {5ED2C481-2D74-43BC-ABAF-1455A052FAA4}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {5ED2C481-2D74-43BC-ABAF-1455A052FAA4}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {5ED2C481-2D74-43BC-ABAF-1455A052FAA4}.Release|Any CPU.Build.0 = Release|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
    GlobalSection(ExtensibilityGlobals) = postSolution
        SolutionGuid = {B2073C2C-0FD3-452B-8047-8134D68E12CE}
    EndGlobalSection
EndGlobal
cylsg/cylsg.utility/CommonHelper.cs
New file
@@ -0,0 +1,850 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace cylsg.utility
{
    /// <summary>
    /// 通用帮助类
    /// </summary>
    public static class CommonHelper
    {
        #region 判断字符串是否为手机号码
        /// <summary>
        /// 判断字符串是否为手机号码
        /// </summary>
        /// <param name="mobilePhoneNumber"></param>
        /// <returns></returns>
        public static bool IsMobile(string mobilePhoneNumber)
        {
            if (mobilePhoneNumber.Length < 11)
            {
                return false;
            }
            //电信手机号码正则
            string dianxin = @"^1[345789][01379]\d{8}$";
            Regex regexDx = new Regex(dianxin);
            //联通手机号码正则
            string liantong = @"^1[345678][01256]\d{8}$";
            Regex regexLt = new Regex(liantong);
            //移动手机号码正则
            string yidong = @"^1[345789][0123456789]\d{8}$";
            Regex regexYd = new Regex(yidong);
            if (regexDx.IsMatch(mobilePhoneNumber) || regexLt.IsMatch(mobilePhoneNumber) || regexYd.IsMatch(mobilePhoneNumber))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion
        #region 检测是否符合email格式
        /// <summary>
        ///     检测是否符合email格式
        /// </summary>
        /// <param name="strEmail">要判断的email字符串</param>
        /// <returns>判断结果</returns>
        public static bool IsValidEmail(string strEmail)
        {
            return Regex.IsMatch(strEmail, @"^[\w\.]+([-]\w+)*@[A-Za-z0-9-_]+[\.][A-Za-z0-9-_]");
        }
        public static bool IsValidDoEmail(string strEmail)
        {
            return Regex.IsMatch(strEmail,
                @"^@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
        }
        #endregion
        #region 检测是否是正确的Url
        /// <summary>
        ///     检测是否是正确的Url
        /// </summary>
        /// <param name="strUrl">要验证的Url</param>
        /// <returns>判断结果</returns>
        public static bool IsUrl(string strUrl)
        {
            return Regex.IsMatch(strUrl,
                @"^(http|https)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{1,10}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$");
        }
        #endregion
        #region string 转int数组
        public static int[] StringToIntArray(string str)
        {
            try
            {
                if (string.IsNullOrEmpty(str)) return new int[0];
                if (str.EndsWith(","))
                {
                    str = str.Remove(str.Length - 1, 1);
                }
                var idstrarr = str.Split(',');
                var idintarr = new int[idstrarr.Length];
                for (int i = 0; i < idstrarr.Length; i++)
                {
                    idintarr[i] = Convert.ToInt32(idstrarr[i]);
                }
                return idintarr;
            }
            catch
            {
                return new int[0];
            }
        }
        #endregion
        #region String转数组
        public static string[] StringToStringArray(string str)
        {
            try
            {
                if (string.IsNullOrEmpty(str)) return new string[0];
                if (str.EndsWith(",")) str = str.Remove(str.Length - 1, 1);
                return str.Split(',');
            }
            catch
            {
                return new string[0];
            }
        }
        #endregion
        #region String数组转Int数组
        public static int[] StringArrAyToIntArray(string[] str)
        {
            try
            {
                int[] iNums = Array.ConvertAll(str, s => int.Parse(s));
                return iNums;
            }
            catch
            {
                return new int[0];
            }
        }
        #endregion
        #region string转Guid数组
        public static Guid[] StringToGuidArray(string str)
        {
            try
            {
                if (string.IsNullOrEmpty(str)) return new Guid[0];
                if (str.EndsWith(",")) str = str.Remove(str.Length - 1, 1);
                var strarr = str.Split(',');
                Guid[] guids = new Guid[strarr.Length];
                for (int index = 0; index < strarr.Length; index++)
                {
                    guids[index] = Guid.Parse(strarr[index]);
                }
                return guids;
            }
            catch
            {
                return new Guid[0];
            }
        }
        #endregion
        #region 转MD5
        /// <summary>
        /// 转MD5
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ToMd5(string str)
        {
            MD5 md5 = MD5.Create();
            // 将字符串转换成字节数组
            byte[] byteOld = Encoding.UTF8.GetBytes(str);
            // 调用加密方法
            byte[] byteNew = md5.ComputeHash(byteOld);
            // 将加密结果转换为字符串
            StringBuilder sb = new StringBuilder();
            foreach (byte b in byteNew)
            {
                // 将字节转换成16进制表示的字符串,
                sb.Append(b.ToString("x2"));
            }
            // 返回加密的字符串
            return sb.ToString();
        }
        #endregion
        #region 获取32位md5加密
        /// <summary>
        /// 通过创建哈希字符串适用于任何 MD5 哈希函数 (在任何平台) 上创建 32 个字符的十六进制格式哈希字符串
        /// </summary>
        /// <param name="source"></param>
        /// <returns>32位md5加密字符串</returns>
        public static string Md5For32(string source)
        {
            using (MD5 md5Hash = MD5.Create())
            {
                byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(source));
                StringBuilder sBuilder = new StringBuilder();
                for (int i = 0; i < data.Length; i++)
                {
                    sBuilder.Append(data[i].ToString("x2"));
                }
                string hash = sBuilder.ToString();
                return hash.ToUpper();
            }
        }
        #endregion
        #region 获取16位md5加密
        /// <summary>
        /// 获取16位md5加密
        /// </summary>
        /// <param name="source"></param>
        /// <returns>16位md5加密字符串</returns>
        public static string Md5For16(string source)
        {
            using (MD5 md5Hash = MD5.Create())
            {
                byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(source));
                //转换成字符串,并取9到25位
                string sBuilder = BitConverter.ToString(data, 4, 8);
                //BitConverter转换出来的字符串会在每个字符中间产生一个分隔符,需要去除掉
                sBuilder = sBuilder.Replace("-", "");
                return sBuilder.ToUpper();
            }
        }
        #endregion
        #region 返回当前的毫秒时间戳
        /// <summary>
        /// 返回当前的毫秒时间戳
        /// </summary>
        public static string Msectime()
        {
            long timeTicks = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000;
            return timeTicks.ToString();
        }
        #endregion
        #region 剩余多久时间文字描述
        /// <summary>
        /// 剩余多久时间
        /// </summary>
        /// <param name="remainingTime"></param>
        /// <returns>文字描述</returns>
        public static string GetRemainingTime(DateTime remainingTime)
        {
            TimeSpan timeSpan = remainingTime - DateTime.Now;
            var day = timeSpan.Days;
            var hours = timeSpan.Hours;
            var minute = timeSpan.Minutes;
            var seconds = timeSpan.Seconds;
            if (day > 0)
            {
                return day + "天" + hours + "小时" + minute + "分" + seconds + "秒";
            }
            else
            {
                if (hours > 0)
                {
                    return hours + "小时" + minute + "分" + seconds + "秒";
                }
                else
                {
                    return minute + "分" + seconds + "秒";
                }
            }
        }
        #endregion
        #region 剩余多久时间返回时间类型
        /// <summary>
        /// 剩余多久时间
        /// </summary>
        /// <param name="remainingTime"></param>
        /// <returns>返回时间类型</returns>
        public static void GetBackTime(DateTime remainingTime, out int day, out int hours, out int minute, out int seconds)
        {
            TimeSpan timeSpan = remainingTime - DateTime.Now;
            day = timeSpan.Days;
            hours = timeSpan.Hours;
            minute = timeSpan.Minutes;
            seconds = timeSpan.Seconds;
        }
        #endregion
        #region 计算时间戳剩余多久时间
        /// <summary>
        /// 计算时间戳剩余多久时间
        /// </summary>
        /// <param name="postTime">提交时间(要是以前的时间)</param>
        /// <returns></returns>
        public static string TimeAgo(DateTime postTime)
        {
            //当前时间的时间戳
            var nowtimes = ConvertTicks(DateTime.Now);
            //提交的时间戳
            var posttimes = ConvertTicks(postTime);
            //相差时间戳
            var counttime = nowtimes - posttimes;
            //进行时间转换
            if (counttime <= 60)
            {
                return "刚刚";
            }
            else if (counttime > 60 && counttime <= 120)
            {
                return "1分钟前";
            }
            else if (counttime > 120 && counttime <= 180)
            {
                return "2分钟前";
            }
            else if (counttime > 180 && counttime < 3600)
            {
                return Convert.ToInt32(counttime / 60) + "分钟前";
            }
            else if (counttime >= 3600 && counttime < 3600 * 24)
            {
                return Convert.ToInt32(counttime / 3600) + "小时前";
            }
            else if (counttime >= 3600 * 24 && counttime < 3600 * 24 * 2)
            {
                return "昨天";
            }
            else if (counttime >= 3600 * 24 * 2 && counttime < 3600 * 24 * 3)
            {
                return "前天";
            }
            else if (counttime >= 3600 * 24 * 3 && counttime <= 3600 * 24 * 7)
            {
                return Convert.ToInt32(counttime / (3600 * 24)) + "天前";
            }
            else if (counttime >= 3600 * 24 * 7 && counttime <= 3600 * 24 * 30)
            {
                return Convert.ToInt32(counttime / (3600 * 24 * 7)) + "周前";
            }
            else if (counttime >= 3600 * 24 * 30 && counttime <= 3600 * 24 * 365)
            {
                return Convert.ToInt32(counttime / (3600 * 24 * 30)) + "个月前";
            }
            else if (counttime >= 3600 * 24 * 365)
            {
                return Convert.ToInt32(counttime / (3600 * 24 * 365)) + "年前";
            }
            else
            {
                return "";
            }
        }
        /// <summary>
        /// 时间转换为秒的时间戳
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        private static long ConvertTicks(DateTime time)
        {
            long currentTicks = time.Ticks;
            DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            long currentMillis = (currentTicks - dtFrom.Ticks) / 10000000;  //转换为秒为Ticks/10000000,转换为毫秒Ticks/10000
            return currentMillis;
        }
        #endregion
        #region 清除HTML中指定样式
        /// <summary>
        /// 清除HTML中指定样式
        /// </summary>
        /// <param name="content"></param>
        /// <param name="rule"></param>
        /// <returns></returns>
        public static string ClearHtml(string content, string[] rule)
        {
            if (!rule.Any())
            {
                return content;
            }
            foreach (var item in rule)
            {
                content = Regex.Replace(content, "/" + item + @"\s*=\s*\d+\s*/i", "");
                content = Regex.Replace(content, "/" + item + @"\s*=\s*.+?[""]/i", "");
                content = Regex.Replace(content, "/" + item + @"\s*:\s*\d+\s*px\s*;?/i", "");
            }
            return content;
        }
        #endregion
        #region list随机排序方法
        /// <summary>
        /// list随机排序方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ListT"></param>
        /// <returns></returns>
        public static List<T> RandomSortList<T>(List<T> ListT)
        {
            Random random = new Random();
            List<T> newList = new List<T>();
            foreach (T item in ListT)
            {
                newList.Insert(random.Next(newList.Count + 1), item);
            }
            return newList;
        }
        #endregion
        #region 截前后字符(串)
        ///<summary>
        /// 截前后字符(串)
        ///</summary>
        ///<param name="val">原字符串</param>
        ///<param name="str">要截掉的字符串</param>
        ///<param name="all">是否贪婪</param>
        ///<returns></returns>
        public static string GetCaptureInterceptedText(string val, string str, bool all = false)
        {
            return Regex.Replace(val, @"(^(" + str + ")" + (all ? "*" : "") + "|(" + str + ")" + (all ? "*" : "") + "$)", "");
        }
        #endregion
        #region 密码加密方法
        /// <summary>
        /// 密码加密方法
        /// </summary>
        /// <param name="password">要加密的字符串</param>
        /// <param name="createTime">时间组合</param>
        /// <returns></returns>
        public static string EnPassword(string password, DateTime createTime)
        {
            var dtStr = createTime.ToString("yyyyMMddHHmmss");
            var md5 = Md5For32(password);
            var enPwd = Md5For32(md5 + dtStr);
            return enPwd;
        }
        #endregion
        #region 获取现在是星期几
        /// <summary>
        /// 获取现在是星期几
        /// </summary>
        /// <returns></returns>
        public static string GetWeek()
        {
            string week = string.Empty;
            switch (DateTime.Now.DayOfWeek)
            {
                case DayOfWeek.Monday:
                    week = "周一";
                    break;
                case DayOfWeek.Tuesday:
                    week = "周二";
                    break;
                case DayOfWeek.Wednesday:
                    week = "周三";
                    break;
                case DayOfWeek.Thursday:
                    week = "周四";
                    break;
                case DayOfWeek.Friday:
                    week = "周五";
                    break;
                case DayOfWeek.Saturday:
                    week = "周六";
                    break;
                case DayOfWeek.Sunday:
                    week = "周日";
                    break;
                default:
                    week = "N/A";
                    break;
            }
            return week;
        }
        #endregion
        #region UrlEncode (URL编码)
        /// <summary>
        /// UrlEncode (URL编码)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string UrlEncode(string str)
        {
            StringBuilder sb = new StringBuilder();
            byte[] byStr = Encoding.UTF8.GetBytes(str); //默认是System.Text.Encoding.Default.GetBytes(str)
            for (int i = 0; i < byStr.Length; i++)
            {
                sb.Append(@"%" + Convert.ToString(byStr[i], 16));
            }
            return sb.ToString();
        }
        #endregion
        #region 获取10位时间戳
        /// <summary>
        /// 获取10位时间戳
        /// </summary>
        /// <returns></returns>
        public static long GetTimeStampByTotalSeconds()
        {
            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds);
        }
        #endregion
        #region 获取13位时间戳
        /// <summary>
        /// 获取13位时间戳
        /// </summary>
        /// <returns></returns>
        public static long GetTimeStampByTotalMilliseconds()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalMilliseconds);
        }
        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static int GetDateTimeStamp(DateTime dt)
        {
            DateTime dateStart = new DateTime(1970, 1, 1, 0, 0, 0);
            int timeStamp = Convert.ToInt32((dt.ToUniversalTime() - dateStart).TotalSeconds);
            return timeStamp;
        }
        #endregion
        #region 获取随机字符串
        /// <summary>
        /// 获取随机字符串
        /// </summary>
        /// <returns></returns>
        public static string GetSerialNumber()
        {
            var str = string.Empty;
            Random rand = new Random();
            var charsStr2 = new[] { 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'P', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
            var charsLen2 = charsStr2.Length - 1;
            //    shuffle($chars);
            str = "";
            for (int i = 0; i < 16; i++)
            {
                str += charsStr2[rand.Next(0, charsLen2)];
            }
            return str;
        }
        #endregion
        #region Sha1签名
        /// <summary>
        /// Sha1签名
        /// </summary>
        /// <param name="str">内容</param>
        /// <param name="encoding">编码</param>
        /// <returns></returns>
        public static string Sha1Signature(string str, Encoding encoding = null)
        {
            if (encoding == null) encoding = Encoding.UTF8;
            var buffer = encoding.GetBytes(str);
            var data = SHA1.Create().ComputeHash(buffer);
            StringBuilder sub = new StringBuilder();
            foreach (var t in data)
            {
                sub.Append(t.ToString("x2"));
            }
            return sub.ToString();
        }
        #endregion
        /// <summary>
        ///  精确计算base64字符串文件大小(单位:B)
        ///  param base64String
        ///  return double 字节大小
        /// </summary>
        /// <param name="base64String"></param>
        /// <returns></returns>
        public static double Base64FileSize(string base64String)
        {
            //检测是否含有base64,文件头)
            if (base64String.LastIndexOf(",", StringComparison.Ordinal) > -1)
            {
                base64String = base64String[(base64String.LastIndexOf(",", StringComparison.Ordinal) + 1)..];
            }
            //获取base64字符串长度(不含data:audio/wav;base64,文件头)
            var size0 = base64String.Length;
            if (size0 <= 10) return size0 - (double)size0 / 8 * 2;
            //获取字符串的尾巴的最后10个字符,用于判断尾巴是否有等号,正常生成的base64文件'等号'不会超过4个
            var tail = base64String[(size0 - 10)..];
            //找到等号,把等号也去掉,(等号其实是空的意思,不能算在文件大小里面)
            int equalIndex = tail.IndexOf("=", StringComparison.Ordinal);
            if (equalIndex > 0)
            {
                size0 = size0 - (10 - equalIndex);
            }
            //计算后得到的文件流大小,单位为字节
            return size0 - (double)size0 / 8 * 2;
        }
        /// <summary>
        /// 判断文件大小
        /// </summary>
        /// <param name="base64"></param>
        /// <param name="size"></param>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static bool CheckBase64Size(string base64, int size, string unit = "M")
        {
            // 上传文件的大小, 单位为字节.
            var len = Base64FileSize(base64);
            // 准备接收换算后文件大小的容器
            double fileSize = unit.ToUpperInvariant() switch
            {
                "B" => len,
                "K" => (double)len / 1024,
                "M" => (double)len / 1048576,
                "G" => (double)len / 1073741824,
                _ => 0
            };
            // 如果上传文件大于限定的容量
            return !(fileSize > size);
        }
        /// <summary>
        /// 10位时间戳 转化
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static long ConvertDateTimeToInt(DateTime time)
        {
            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, 0));
            long t = (time.Ticks - startTime.Ticks) / 10000000;   //除10000000调整为10位
            return t;
        }
        #region 反射相关
        private static List<Assembly>? _allAssemblies = null;
        /// <summary>
        /// 获取所有程序目录下和常用的程序集 包括一些系统引用程序集
        /// </summary>
        /// <returns> 当前工程下的程序集</returns>
        public static List<Assembly> GetAllAssembly()
        {
            if (_allAssemblies == null)
            {
                _allAssemblies = new List<Assembly>();
                string? path = null;
                string singlefile = null;
                try
                {
                    path = Assembly.GetEntryAssembly()?.Location;
                }
                catch { }
                if (string.IsNullOrEmpty(path))
                {
                    singlefile = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
                    path = Path.GetDirectoryName(singlefile);
                }
                if (string.IsNullOrEmpty(path))
                    throw new Exception("获取程序目录出错");
                var dir = new DirectoryInfo(Path.GetDirectoryName(path) ?? "");
                var dlls = dir.GetFiles("*.dll", SearchOption.TopDirectoryOnly);
                string[] systemdll = new string[]
                {
                "Microsoft.",
                "System.",
                "Swashbuckle.",
                "ICSharpCode",
                "Newtonsoft.",
                "Oracle.",
                "Pomelo.",
                "SQLitePCLRaw.",
                "Aliyun.OSS",
                "BouncyCastle.",
                "FreeSql.",
                "Google.Protobuf.dll",
                "Humanizer.dll",
                "IdleBus.dll",
                "K4os.",
                "MySql.Data.",
                "Npgsql.",
                "NPOI.",
                "netstandard",
                "MySqlConnector",
                "VueCliMiddleware"
                };
                var filtered = dlls.Where(x => systemdll.Any(y => x.Name.StartsWith(y)) == false);
                foreach (var dll in filtered)
                {
                    try
                    {
                        AssemblyLoadContext.Default.LoadFromAssemblyPath(dll.FullName);
                    }
                    catch
                    {
                    }
                }
                var dlllist = AssemblyLoadContext.Default.Assemblies.Where(x => systemdll.Any(y => x.FullName.StartsWith(y)) == false).ToList();
                _allAssemblies.AddRange(dlllist);
            }
            return _allAssemblies;
        }
        #endregion
        #region 枚举获取所有项
        /// <summary>
        /// 获取枚举的所有项
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static List<MenmItem> GetEnumItemsWithAttributes<T>() where T : Enum
        {
            var result = new List<MenmItem>();
            foreach (var value in Enum.GetValues(typeof(T)))
            {
                var member = typeof(T).GetMember(value.ToString())[0];
                var descriptionAttribute = member.GetCustomAttribute<DescriptionAttribute>();
                var item = new MenmItem
                {
                    Key = value.ToString(),
                    Value = (int)value, // 或者直接使用 value.ToString() 如果不需要转换为整数字符串
                    Description = descriptionAttribute?.Description ?? string.Empty
                };
                result.Add(item);
            }
            return result;
        }
        /// <summary>
        /// 获取枚举所有的项,返回名称 值 和Description 描述
        /// </summary>
        /// <param name="enumType"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static List<MenmItem> EnumerateWithDescriptions(Type enumType)
        {
            if (!enumType.IsEnum)
            {
                throw new ArgumentException(" 这不是枚举");
            }
            var result = new List<MenmItem>();
            foreach (var value in Enum.GetValues(enumType))
            {
                var member = enumType.GetMember(value.ToString())[0];
                var descriptionAttribute = member.GetCustomAttribute<DescriptionAttribute>();
                var item = new MenmItem
                {
                    Key = value.ToString(),
                    Value = (int)value, // 或者直接使用 value.ToString() 如果不需要转换为整数字符串
                    Description = descriptionAttribute?.Description ?? string.Empty
                };
                result.Add(item);
            }
            return result;
        }
        /// <summary>
        /// 是否是系统类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsCustomType(Type type)
        {
            // 定义一个或多个基础命名空间列表,这些命名空间下的类型通常认为是系统类型
            string[] frameworkNamespaces = { "System", "Microsoft", "mscorlib", "netstandard", "System.Private.CoreLib" };
            // 获取类型所在的命名空间
            string typeNameSpace = type.Namespace;
            // 检查该命名空间是否在基础命名空间列表中,如果不在,则认为是自定义类型
            return frameworkNamespaces.Any(n => typeNameSpace.StartsWith(n, StringComparison.OrdinalIgnoreCase));
        }
        #endregion
    }
    /// <summary>
    /// 枚举项属性
    /// </summary>
    [Description("枚举项属性")]
    public class MenmItem
    {
        /// <summary>
        /// 枚举key
        /// </summary>
        [Description("枚举key")]
        public string? Key { get; set; }
        /// <summary>
        /// 枚举值
        /// </summary>
        [Description("枚举值")]
        public int Value { get; set; }
        /// <summary>
        /// 枚举描述
        /// </summary>
        [Description("枚举项属性")]
        public string? Description { get; set; }
    }
}
cylsg/cylsg.utility/Extend/EmunEx.cs
New file
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cylsg.utility.Extend
{
    /// <summary>
    /// 枚举扩展
    /// </summary>
    public static class EmunEx
    {
    }
}
cylsg/cylsg.utility/Extend/StringEx.cs
New file
@@ -0,0 +1,236 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace cylsg.utility.Extend
{
    /// <summary>
    /// 字符串扩展
    /// </summary>
    public static class StringEx
    {
        /// <summary>
        /// 首字母小写
        /// </summary>
        /// <param name="self"></param>
        /// <returns></returns>
        public static string FirstToLower(this string self)
        {
            string str1 = self?.Substring(0, 1).ToLower() ?? "";
            string str2 = self?.Substring(1) ?? "";
            //首字母转小写
            return str1 + str2;
        }
        /// <summary>
        /// 带有xxx.xxx结束的的所有字符串 的后面xxx.xxx
        /// </summary>
        /// <param name="strtypr"></param>
        /// <returns></returns>
        public static string GetFileName(this string strtypr)
        {
            return Path.GetFileName(strtypr);
        }
        /// <summary>
        /// 是否是数字序列
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool isPureNum(this string strtypr)
        {
            if (strtypr.Length == 0 || strtypr == null)//验证这个字符串是否为空
            {
                return false;
            }
            byte[] strBytes = Encoding.ASCII.GetBytes(strtypr);//获取字符串的byte类型的字符数组,编码方式ASCII
            foreach (byte strByte in strBytes)
            {
                if (strByte < 48 || strByte > 57)     //判断每个字符是否为数字,根据每个字符的ASCII值所在范围判断
                {
                    return false;                     //不是,就返回false
                }
            }
            return true;                              //是,就返回true
        }
        /// <summary>
        /// 是否是数字序列
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool isGuid(this string strtypr)
        {
            if (strtypr.Length < 20 || strtypr == null)//验证这个字符串是否为空
            {
                return false;
            }
            try
            {
                new Guid(strtypr);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        /// 字符串
        /// </summary>
        /// <param name="strtypr"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static int toInt(this string strtypr)
        {
            if (!strtypr.isPureNum())
                throw new Exception("并非完整的数字序列");
            return int.Parse(strtypr);
        }
        /// <summary>
        /// 移除第一个字符串为指定字符串的 如 “axtXXXXX" 如果以"axt"开头的字符串,就移除"axt" 没有则不变
        /// </summary>
        /// <param name="strtypr"></param>
        /// <param name="str">开始字符</param>
        /// <returns></returns>
        public static string RemoveStartWithStr(this string strtypr, string str)
        {
            string strret = strtypr;
            if (strtypr.StartsWith(str))
            {
                strret = strtypr.Remove(0, str.Length);
            }
            return strret;
        }
        /// <summary>
        /// 对字符串进行隐私处理,比如中间的用*显示
        /// </summary>
        /// <param name="strtypr"></param>
        /// <returns></returns>
        public static string PrivacyStr(this string strtypr)
        {
            // 如果是手机号码,仅保留前3位和后4位,中间用星号替换
            if (Regex.IsMatch(strtypr, @"^1[3-9]\d{9}$"))
            {
                return $"{strtypr.Substring(0, 3)}****{strtypr.Substring(7)}";
            }
            // 对于中文名字或者非手机号格式,仅保留首尾各1个字符,中间用星号替换
            else
            {
                if (strtypr.Length <= 2) return $"{strtypr.Substring(0, 1)}*"; // 长度小于等于2时,返回固定的星号
                var masked = $"{strtypr.Substring(0, 1)}*{strtypr.Substring(strtypr.Length - 1, 1)}";
                return masked;
            }
        }
        #region 时间区间字符串转其实和结束时间
        /// <summary>
        /// 解析时间区间字符串
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static (DateTime? StartDate, DateTime? EndDate) TryParseDateRangString(this string input)
        {
            DateTime startDate, endDate;
            var culture = CultureInfo.InvariantCulture;
            // 尝试解析第一种格式 "2023-01-012023-01-31"
            if (DateTime.TryParseExact(input.Substring(0, 10), "yyyy-MM-dd", culture, DateTimeStyles.None, out startDate) &&
                DateTime.TryParseExact(input.Substring(10), "yyyy-MM-dd", culture, DateTimeStyles.None, out endDate))
            {
                return (startDate, endDate);
            }
            // 尝试解析第二种格式 "2023-01-01 08:02:032023-01-31 08:02:03"
            if (DateTime.TryParseExact(input.Substring(0, 19), "yyyy-MM-dd HH:mm:ss", culture, DateTimeStyles.None, out startDate) &&
                DateTime.TryParseExact(input.Substring(19), "yyyy-MM-dd HH:mm:ss", culture, DateTimeStyles.None, out endDate))
            {
                return (startDate, endDate);
            }
            // 尝试解析第二种格式 "2023-01-01T08:02:032023-01-31T08:02:03"
            if (DateTime.TryParseExact(input.Substring(0, 19), "yyyy-MM-ddTHH:mm:ss", culture, DateTimeStyles.None, out startDate) &&
                DateTime.TryParseExact(input.Substring(19), "yyyy-MM-ddTHH:mm:ss", culture, DateTimeStyles.None, out endDate))
            {
                return (startDate, endDate);
            }
            // 如果都不是,返回null
            return (null, null);
        }
        /// <summary>
        /// 移除最后一个字符的?号
        /// </summary>
        /// <param name="input"> </param>
        /// /// <param name="inChar">字符</param>
        /// <returns></returns>
        public static string RemoveCharIfPresent(this string input, char inChar)
        {
            if (string.IsNullOrEmpty(input)) return input;
            // 检查字符串的最后一个字符是否为问号
            if (input[^1] == '?')
            {
                // 使用切片操作符创建不包含问号的新字符串
                return input[..^1];
            }
            else
            {
                // 字符串不以问号结尾,返回原字符串
                return input;
            }
        }
        /// <summary>
        /// 移除最后的字符串
        /// </summary>
        /// <param name="input"></param>
        /// <param name="endString"></param>
        /// <returns></returns>
        public static string RemoveEndStringIfExists(this string input, string endString)
        {
            if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(endString))
            {
                return input; // 如果输入字符串或结束字符串为空或null,直接返回原字符串
            }
            if (input.EndsWith(endString))
            {
                return input.Substring(0, input.Length - endString.Length); // 移除结束字符串
            }
            return input; // 如果不以指定字符串结束,返回原字符串
        }
        /// <summary>
        /// 首字母转小写
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string FirstCharToLower(this string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return input;
            }
            // 使用正则表达式
            return Regex.Replace(input, @"^\p{Lu}", match => match.Value.ToLower());
        }
        #endregion
    }
}
cylsg/cylsg.utility/Extend/TypeAndExpressionEx.cs
New file
@@ -0,0 +1,1021 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using cylsg.utility.Extend;
using Microsoft.Extensions.Primitives;
namespace cylsg.utility.Extend
{
    /// <summary>
    /// 反射扩展函数
    /// </summary>
    public static class TypeAndExpressionEx
    {
        #region 属性扩展 反射
        public static Func<object, object> GetPropertyExpression(Type objtype, string property)
        {
            property = Regex.Replace(property, @"\[[^\]]*\]", string.Empty);
            List<string> level = new List<string>();
            if (property.Contains('.'))
            {
                level.AddRange(property.Split('.'));
            }
            else
            {
                level.Add(property);
            }
            var pe = Expression.Parameter(objtype);
#pragma warning disable 8604
            var member = Expression.Property(pe, objtype.GetSingleProperty(level[0]));
            for (int i = 1; i < level.Count; i++)
            {
                member = Expression.Property(member, member.Type.GetSingleProperty(level[i]));
            }
            return Expression.Lambda<Func<object, object>>(member, pe).Compile();
        }
        /// <summary>
        /// 获取属性名
        /// </summary>
        /// <param name="expression">属性表达式</param>
        /// <param name="getAll">是否获取全部级别名称,比如a.b.c</param>
        /// <returns>属性名</returns>
        public static string GetPropertyName(this Expression expression, bool getAll = true)
        {
            if (expression == null)
            {
                return "";
            }
            MemberExpression me = null;
            LambdaExpression le = null;
            if (expression is MemberExpression)
            {
                me = expression as MemberExpression;
            }
            if (expression is LambdaExpression)
            {
                le = expression as LambdaExpression;
                if (le.Body is MemberExpression)
                {
                    me = le.Body as MemberExpression;
                }
                if (le.Body is UnaryExpression)
                {
                    me = (le.Body as UnaryExpression).Operand as MemberExpression;
                }
            }
            string rv = "";
            if (me != null)
            {
                rv = me.Member.Name;
            }
            while (me != null && getAll && me.NodeType == ExpressionType.MemberAccess)
            {
                Expression exp = me.Expression;
                if (exp is MemberExpression)
                {
                    rv = (exp as MemberExpression).Member.Name + "." + rv;
                    me = exp as MemberExpression;
                }
                else if (exp is MethodCallExpression)
                {
                    var mexp = exp as MethodCallExpression;
                    if (mexp.Method.Name == "get_Item")
                    {
                        object index = 0;
                        if (mexp.Arguments[0] is MemberExpression)
                        {
                            var obj = ((mexp.Arguments[0] as MemberExpression).Expression as ConstantExpression).Value;
                            index = obj.GetType().GetField((mexp.Arguments[0] as MemberExpression).Member.Name).GetValue(obj);
                        }
                        else
                        {
                            index = (mexp.Arguments[0] as ConstantExpression).Value;
                        }
                        rv = (mexp.Object as MemberExpression).Member.Name + "[" + index + "]." + rv;
                        me = mexp.Object as MemberExpression;
                    }
                }
                else
                {
                    break;
                }
            }
            return rv;
        }
        public static Expression GetMemberExp(this ParameterExpression self, Expression member)
        {
            return self.GetMemberExp(member.GetPropertyName());
        }
        public static Expression GetMemberExp(this ParameterExpression self, string memberName)
        {
            var names = memberName.Split(',');
            Expression rv = Expression.PropertyOrField(self, names[0]); ;
            for (int i = 1; i < names.Length; i++)
            {
                rv = Expression.PropertyOrField(rv, names[i]);
            }
            return rv;
        }
        /// <summary>
        /// 获取正则表达式错误
        /// </summary>
        /// <param name="pi">属性信息</param>
        /// <returns>错误文本</returns>
        public static string GetRegexErrorMessage(this MemberInfo pi)
        {
            string rv = "";
            if (pi.GetCustomAttributes(typeof(RegularExpressionAttribute), false).FirstOrDefault() is RegularExpressionAttribute dis && !string.IsNullOrEmpty(dis.ErrorMessage))
            {
                rv = dis.ErrorMessage;
                //if (CoreProgram._localizer != null)
                //{
                //    rv = CoreProgram._localizer[rv];
                //}
            }
            else
            {
                rv = "";
            }
            return rv;
        }
        /// <summary>
        /// 获取属性显示名称
        /// </summary>
        /// <param name="pi">属性信息</param>
        /// <returns>属性名称</returns>
        public static string GetPropertyDisplayName(this MemberInfo pi)
        {
            string rv = "";
            if (pi.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault() is DisplayAttribute dis && !string.IsNullOrEmpty(dis.Name))
            {
                rv = dis.Name;
            }
            else
            {
                rv = pi.Name;
            }
            return rv;
        }
        /// <summary>
        /// 获取属性显示名称
        /// </summary>
        /// <param name="expression">属性表达式</param>
        /// <returns>属性显示名称</returns>
        public static string GetPropertyDisplayName(this Expression expression)
        {
            return expression.GetPropertyInfo().GetPropertyDisplayName();
        }
        /// <summary>
        /// 获取属性的 Description 标注名,如果没有,则返回 属性名称
        /// </summary>
        /// <param name="pi"></param>
        /// <returns></returns>
        public static string GetPropertyDescription(this MemberInfo pi)
        {
            string rv = "";
            if (pi.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault() is DescriptionAttribute dis && !string.IsNullOrEmpty(dis.Description))
            {
                rv = dis.Description;
            }
            else
            {
                rv = pi.Name;
            }
            return rv;
        }
        /// <summary>
        /// 获取属性的 Description 标注名,如果没有,则返回 属性名称
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static string GetPropertyDescription(this Expression expression)
        {
            return expression.GetPropertyInfo().GetPropertyDisplayName();
        }
        /// <summary>
        /// 获取枚举显示名称
        /// </summary>
        /// <param name="value">枚举值</param>
        /// <returns>枚举显示名称</returns>
        public static string? GetEnumDisplayName(this Enum value)
        {
            return GetEnumDisplayName(value.GetType(), value.ToString());
        }
        /// <summary>
        /// 获取属性信息
        /// </summary>
        /// <param name="expression">属性表达式</param>
        /// <returns>属性信息</returns>
        public static PropertyInfo? GetPropertyInfo(this Expression expression)
        {
            MemberExpression me = null;
            LambdaExpression le = null;
            if (expression is MemberExpression)
            {
                me = expression as MemberExpression;
            }
            if (expression is LambdaExpression)
            {
                le = expression as LambdaExpression;
                if (le.Body is MemberExpression)
                {
                    me = le.Body as MemberExpression;
                }
                if (le.Body is UnaryExpression)
                {
                    me = (le.Body as UnaryExpression).Operand as MemberExpression;
                }
            }
            PropertyInfo rv = null;
            if (me != null)
            {
                rv = me.Member.DeclaringType.GetSingleProperty(me.Member.Name);
            }
            return rv;
        }
        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="exp">属性表达式</param>
        /// <param name="obj">属性所在实例</param>
        /// <returns>属性值</returns>
        public static object? GetPropertyValue(this object obj, LambdaExpression exp)
        {
            //获取表达式的值,并过滤单引号
            try
            {
                var expValue = exp.Compile().DynamicInvoke(obj);
                object val = expValue;
                return val;
            }
            catch
            {
                return "";
            }
        }
        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        public static object? GetPropertyValue(this object obj, string property)
        {
            //获取表达式的值,并过滤单引号
            try
            {
                return obj.GetType().GetSingleProperty(property).GetValue(obj);
            }
            catch
            {
                return null;
            }
        }
        public static List<string>? GetPropertySiblingValues(this object obj, string propertyName)
        {
            if (obj == null)
            {
                return new List<string>();
            }
            Regex reg = new Regex("(.*?)\\[\\-?\\d?\\]\\.(.*?)$");
            var match = reg.Match(propertyName);
            if (match.Success)
            {
                var name1 = match.Groups[1].Value;
                var name2 = match.Groups[2].Value;
                var levels = name1.Split('.');
                var objtype = obj.GetType();
                var pe = Expression.Parameter(objtype);
                var member = Expression.Property(pe, objtype.GetSingleProperty(levels[0]));
                for (int i = 1; i < levels.Length; i++)
                {
                    member = Expression.Property(member, member.Type.GetSingleProperty(levels[i]));
                }
                var pe2 = Expression.Parameter(member.Type.GetGenericArguments()[0]);
                var cast = Expression.Call(typeof(Enumerable), "Cast", new Type[] { pe2.Type }, member);
                var name2exp = Expression.Property(pe2, pe2.Type.GetSingleProperty(name2));
                var selectexp = Expression.Call(name2exp, "ToString", Type.EmptyTypes);
                Expression select = Expression.Call(
                               typeof(Enumerable),
                               "Select",
                               new Type[] { pe2.Type, typeof(string) },
                               cast,
                               Expression.Lambda(selectexp, pe2));
                var lambda = Expression.Lambda(select, pe);
                var rv = new List<string>();
                try
                {
                    rv = (lambda.Compile().DynamicInvoke(obj) as IEnumerable<string>)?.ToList();
                }
                catch { }
                return rv;
            }
            else
            {
                return new List<string>();
            }
        }
        /// <summary>
        /// 判断属性是否必填
        /// </summary>
        /// <param name="pi">属性信息</param>
        /// <returns>是否必填</returns>
        public static bool IsPropertyRequired(this MemberInfo pi)
        {
            bool isRequired = false;
            if (pi != null)
            {
                //如果需要显示星号,则判断是否是必填项,如果是必填则在内容后面加上星号
                //所有int,float。。。这种Primitive类型的,肯定都是必填
                Type t = pi.GetMemberType();
                if (t != null && (t.IsPrimitive() || t.IsEnum() || t == typeof(decimal) || t == typeof(Guid)))
                {
                    isRequired = true;
                }
                else
                {
                    //对于其他类,检查是否有RequiredAttribute,如果有就是必填
                    if (pi.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault() is RequiredAttribute required && required.AllowEmptyStrings == false)
                    {
                        isRequired = true;
                    }
                    else if (pi.GetCustomAttributes(typeof(KeyAttribute), false).FirstOrDefault() != null)
                    {
                        isRequired = true;
                    }
                }
            }
            return isRequired;
        }
        /// <summary>
        /// 设置属性值
        /// </summary>
        /// <param name="source">属性所在实例</param>
        /// <param name="property">属性名</param>
        /// <param name="value">要赋的值</param>
        /// <param name="prefix">属性前缀</param>
        /// <param name="stringBasedValue">是否为字符串格式的值</param>
        public static void SetPropertyValue(this object source, string property, object value, string? prefix = null, bool stringBasedValue = false)
        {
            try
            {
                property = Regex.Replace(property, @"\[[^\]]*\]", string.Empty);
                List<string> level = new List<string>();
                if (property.Contains('.'))
                {
                    level.AddRange(property.Split('.'));
                }
                else
                {
                    level.Add(property);
                }
                if (!string.IsNullOrWhiteSpace(prefix))
                {
                    level.Insert(0, prefix);
                }
                object temp = source;
                Type tempType = source.GetType();
                for (int i = 0; i < level.Count - 1; i++)
                {
                    var member = tempType.GetMember(level[i])[0];
                    if (member != null)
                    {
                        var va = member.GetMemberValue(temp);
                        if (va != null)
                        {
                            temp = va;
                        }
                        else
                        {
                            var newInstance = member.GetMemberType().GetConstructor(Type.EmptyTypes).Invoke(null);
                            member.SetMemberValue(temp, newInstance, null);
                            temp = newInstance;
                        }
                        tempType = member.GetMemberType();
                    }
                }
                var memberInfos = tempType.GetMember(level.Last());
                if (!memberInfos.Any())
                {
                    return;
                }
                var fproperty = memberInfos[0];
                if (value == null || value is StringValues s && StringValues.IsNullOrEmpty(s))
                {
                    fproperty.SetMemberValue(temp, null, null);
                    return;
                }
                bool isArray = false;
                if (value != null && value.GetType().IsArray == true)
                {
                    isArray = true;
                }
                if (stringBasedValue == true)
                {
                    Type propertyType = fproperty.GetMemberType();
                    if (propertyType.IsGeneric(typeof(List<>)) == true)
                    {
                        var list = propertyType.GetConstructor(Type.EmptyTypes).Invoke(null) as IList;
                        var gs = propertyType.GenericTypeArguments;
                        try
                        {
                            if (value.GetType() == typeof(StringValues))
                            {
                                var strVals = (StringValues)value;
                                var a = strVals.ToArray();
                                for (int i = 0; i < a.Length; i++)
                                {
                                    list.Add(a[i].ConvertValue(gs[0]));
                                }
                            }
                            else if (isArray)
                            {
                                var a = value as object[];
                                for (int i = 0; i < a.Length; i++)
                                {
                                    list.Add(a[i].ConvertValue(gs[0]));
                                }
                            }
                            else
                            {
                                list = value.ConvertValue(propertyType) as IList;
                            }
                        }
                        catch { }
                        fproperty.SetMemberValue(temp, list, null);
                    }
                    else if (propertyType.IsArray)
                    {
                        try
                        {
                            var strVals = (StringValues)value;
                            var eletype = propertyType.GetElementType();
                            if (eletype != null)
                            {
                                var arr = Array.CreateInstance(eletype, strVals.Count);
                                for (int i = 0; i < arr.Length; i++)
                                {
                                    arr.SetValue(strVals[i].ConvertValue(eletype), i);
                                }
                                fproperty.SetMemberValue(temp, arr, null);
                            }
                        }
                        catch { }
                    }
                    else
                    {
                        if (isArray)
                        {
                            var a = value as object[];
                            if (a.Length == 1)
                            {
                                value = a[0];
                            }
                        }
                        if (value is string)
                        {
                            value = value.ToString().Replace("\\", "/");
                        }
                        fproperty.SetMemberValue(temp, value, null);
                    }
                }
                else
                {
                    if (value is string)
                    {
                        value = value.ToString().Replace("\\", "/");
                    }
                    fproperty.SetMemberValue(temp, value, null);
                }
            }
            catch
            {
            }
        }
        /// <summary>
        /// 根据MemberInfo获取值
        /// </summary>
        /// <param name="mi">MemberInfo</param>
        /// <param name="obj">所在实例</param>
        /// <param name="index">如果是数组,指定数组下标。默认为null</param>
        /// <returns>MemberInfo的值</returns>
        public static object? GetMemberValue(this MemberInfo mi, object obj, object[]? index = null)
        {
            object rv = null;
            if (mi.MemberType == MemberTypes.Property)
            {
                rv = ((PropertyInfo)mi).GetValue(obj, index);
            }
            else if (mi.MemberType == MemberTypes.Field)
            {
                rv = ((FieldInfo)mi).GetValue(obj);
            }
            return rv;
        }
        /// <summary>
        /// 设定MemberInfo的值
        /// </summary>
        /// <param name="mi">MemberInfo</param>
        /// <param name="obj">所在实例</param>
        /// <param name="val">要赋的值</param>
        /// <param name="index">如果是数组,指定数组下标。默认为null</param>
        public static void SetMemberValue(this MemberInfo mi, object obj, object val, object[]? index = null)
        {
            object newval = val;
            if (val is string s)
            {
                if (string.IsNullOrEmpty(s))
                {
                    val = null;
                }
            }
            if (val != null && val.GetType() != mi.GetMemberType())
            {
                newval = val.ConvertValue(mi.GetMemberType());
            }
            if (mi.MemberType == MemberTypes.Property)
            {
                ((PropertyInfo)mi).SetValue(obj, newval, index);
            }
            else if (mi.MemberType == MemberTypes.Field)
            {
                ((FieldInfo)mi).SetValue(obj, newval);
            }
        }
        /// <summary>
        /// 获取某个MemberInfo的类型
        /// </summary>
        /// <param name="mi">MemberInfo</param>
        /// <returns>类型</returns>
        public static Type? GetMemberType(this MemberInfo mi)
        {
            Type? rv = null;
            if (mi != null)
            {
                if (mi.MemberType == MemberTypes.Property)
                {
                    rv = ((PropertyInfo)mi).PropertyType;
                }
                else if (mi.MemberType == MemberTypes.Field)
                {
                    rv = ((FieldInfo)mi).FieldType;
                }
            }
            return rv;
        }
        /// <summary>
        /// 获取枚举显示名称
        /// </summary>
        /// <param name="enumType">枚举类型</param>
        /// <param name="value">枚举值</param>
        /// <returns>枚举显示名称</returns>
        public static string? GetEnumDisplayName(Type enumType, string value)
        {
            string rv = "";
            FieldInfo field = null;
            if (enumType.IsEnum())
            {
                field = enumType.GetField(value);
            }
            //如果是nullable的枚举
            if (enumType.IsGeneric(typeof(Nullable<>)) && enumType.GetGenericArguments()[0].IsEnum())
            {
                field = enumType.GenericTypeArguments[0].GetField(value);
            }
            if (field != null)
            {
                var attribs = field.GetCustomAttributes(typeof(DisplayAttribute), true).ToList();
                if (attribs.Count > 0)
                {
                    rv = ((DisplayAttribute)attribs[0]).GetName();
                    //if (CoreProgram._localizer != null)
                    //{
                    //    rv = CoreProgram._localizer[rv];
                    //}
                }
                else
                {
                    rv = value;
                }
            }
            return rv;
        }
        public static string? GetEnumDisplayName(Type enumType, int value)
        {
            string? rv = "";
            FieldInfo? field = null;
            string? ename = "";
            if (enumType.IsEnum())
            {
                ename = enumType.GetEnumName(value);
                field = enumType.GetField(ename ?? "");
            }
            //如果是nullable的枚举
            if (enumType.IsGeneric(typeof(Nullable<>)) && enumType.GetGenericArguments()[0].IsEnum())
            {
                ename = enumType.GenericTypeArguments[0].GetEnumName(value);
                field = enumType.GenericTypeArguments[0].GetField(ename ?? "");
            }
            if (field != null)
            {
                var attribs = field.GetCustomAttributes(typeof(DisplayAttribute), true).ToList();
                if (attribs.Count > 0)
                {
                    rv = ((DisplayAttribute)attribs[0]).GetName();
                    //if (CoreProgram._localizer != null)
                    //{
                    //    rv = CoreProgram._localizer[rv];
                    //}
                }
                else
                {
                    rv = ename;
                }
            }
            return rv;
        }
        /// <summary>
        /// 转化值
        /// </summary>
        /// <param name="value">要转换的值</param>
        /// <param name="propertyType">转换后的类型</param>
        /// <returns>转换后的值</returns>
        public static object? ConvertValue(this object value, Type propertyType)
        {
            object val = null;
            if (propertyType.IsGeneric(typeof(Nullable<>)) == true)
            {
                var gs = propertyType.GenericTypeArguments;
                try
                {
                    val = value.ConvertValue(gs[0]);
                }
                catch { }
            }
            else if (propertyType.IsEnum())
            {
                val = Enum.Parse(propertyType, value.ToString());
            }
            else if (propertyType == typeof(string))
            {
                val = value?.ToString().Trim();
            }
            else if (propertyType == typeof(Guid))
            {
                bool suc = Guid.TryParse(value?.ToString(), out Guid g);
                if (suc)
                {
                    val = g;
                }
                else
                {
                    val = Guid.Empty;
                }
            }
            else
            {
                try
                {
                    if (value.ToString().StartsWith("`") && value.ToString().EndsWith("`"))
                    {
                        string inner = value.ToString().Trim('`').TrimEnd(',');
                        if (!string.IsNullOrWhiteSpace(inner))
                        {
                            val = propertyType.GetConstructor(Type.EmptyTypes).Invoke(null);
                            string[] pair = inner.Split(',');
                            var gs = propertyType.GetGenericArguments();
                            foreach (var p in pair)
                            {
                                (val as IList).Add(Convert.ChangeType(p, gs[0]));
                            }
                        }
                    }
                    else
                    {
                        val = Convert.ChangeType(value.ToString(), propertyType);
                    }
                }
                catch
                {
                }
            }
            return val;
        }
        public static object MakeList(Type innerType, string propertyName, object[] values)
        {
            object rv = typeof(List<>).MakeGenericType(innerType).GetConstructor(Type.EmptyTypes).Invoke(null);
            var mi = rv.GetType().GetMethod("Add");
            var con = innerType.GetConstructor(Type.EmptyTypes);
            foreach (var item in values)
            {
                var newobj = con.Invoke(null);
                newobj.SetPropertyValue(propertyName, item);
                mi.Invoke(rv, new object[] { newobj });
            }
            return rv;
        }
        /// <summary>
        /// 获取 是否定义该标签属性
        /// </summary>
        /// <param name="pi"></param>
        /// <param name="local"></param>
        /// <returns></returns>
        public static T? GetAttribute<T>(this MemberInfo pi) where T : Attribute
        {
            string rv = "";
            if (pi.GetCustomAttributes(typeof(T), false).FirstOrDefault() is T dis)
            {
                return dis;
            }
            else
            {
                return null;
            }
        }
        public static ImmutableDictionary<string, List<PropertyInfo>> _propertyCache { get; set; } =
          new Dictionary<string, List<PropertyInfo>>().ToImmutableDictionary();
        /// <summary>
        /// 判断是否是泛型
        /// </summary>
        /// <param name="self">Type类</param>
        /// <param name="innerType">泛型类型</param>
        /// <returns>判断结果</returns>
        public static bool IsGeneric(this Type self, Type innerType)
        {
            if (self.GetTypeInfo().IsGenericType && self.GetGenericTypeDefinition() == innerType)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 判断是否为Nullable<>类型
        /// </summary>
        /// <param name="self">Type类</param>
        /// <returns>判断结果</returns>
        public static bool IsNullable(this Type self)
        {
            return self.IsGeneric(typeof(Nullable<>));
        }
        /// <summary>
        /// 判断是否为List<>类型
        /// </summary>
        /// <param name="self">Type类</param>
        /// <returns>判断结果</returns>
        public static bool IsList(this Type self)
        {
            return self.IsGeneric(typeof(List<>)) || self.IsGeneric(typeof(IEnumerable<>));
        }
        /// <summary>
        /// 判断是否为List<>类型
        /// </summary>
        /// <param name="self">Type类</param>
        /// <returns>判断结果</returns>
        public static bool IsListOf<T>(this Type self)
        {
            if (self.IsGeneric(typeof(List<>)) && typeof(T).IsAssignableFrom(self.GenericTypeArguments[0]))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #region 判断是否为枚举
        /// <summary>
        /// 判断是否为枚举
        /// </summary>
        /// <param name="self">Type类</param>
        /// <returns>判断结果</returns>
        public static bool IsEnum(this Type self)
        {
            return self.GetTypeInfo().IsEnum;
        }
        /// <summary>
        /// 判断是否为枚举或者可空枚举
        /// </summary>
        /// <param name="self"></param>
        /// <returns></returns>
        public static bool IsEnumOrNullableEnum(this Type self)
        {
            if (self == null)
            {
                return false;
            }
            if (self.IsEnum)
            {
                return true;
            }
            else
            {
                if (self.IsGenericType && self.GetGenericTypeDefinition() == typeof(Nullable<>) && self.GetGenericArguments()[0].IsEnum)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        #endregion
        /// <summary>
        /// 判断是否为值类型 基础值类型
        /// </summary>
        /// <param name="self">Type类</param>
        /// <returns>判断结果</returns>
        public static bool IsPrimitive(this Type self)
        {
            return self.GetTypeInfo().IsPrimitive || self == typeof(decimal);
        }
        /// <summary>
        /// 判断值是否是数字基础类型
        /// </summary>
        /// <param name="self"></param>
        /// <returns></returns>
        public static bool IsNumber(this Type self)
        {
            Type checktype = self;
            if (self.IsNullable())
            {
                checktype = self.GetGenericArguments()[0];
            }
            if (checktype == typeof(int) || checktype == typeof(short) || checktype == typeof(long) || checktype == typeof(float) || checktype == typeof(decimal) || checktype == typeof(double))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #region 判断是否是Bool
        /// <summary>
        /// 是否是bool类型
        /// </summary>
        /// <param name="self"></param>
        /// <returns></returns>
        public static bool IsBool(this Type self)
        {
            return self == typeof(bool);
        }
        /// <summary>
        /// 判断是否是 bool or bool?类型
        /// </summary>
        /// <param name="self"></param>
        /// <returns></returns>
        public static bool IsBoolOrNullableBool(this Type self)
        {
            if (self == null)
            {
                return false;
            }
            if (self == typeof(bool) || self == typeof(bool?))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion
        /// <summary>
        /// 根据名字获取
        /// </summary>
        /// <param name="self"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static PropertyInfo? GetSingleProperty(this Type self, string name)
        {
            if (self.FullName == null)
                throw new Exception("属性名为空");
            if (_propertyCache.ContainsKey(self.FullName) == false)
            {
                var properties = self.GetProperties().ToList();
                _propertyCache = _propertyCache.Add(self.FullName, properties);
                return properties.Where(x => x.Name == name).FirstOrDefault();
            }
            else
            {
                return _propertyCache[self.FullName].Where(x => x.Name == name).FirstOrDefault();
            }
        }
        /// <summary>
        /// 获取属性列表 并将 列表属性放入缓存
        /// </summary>
        /// <param name="self"></param>
        /// <returns></returns>
        public static PropertyInfo? GetSingleProperty(this Type self, Func<PropertyInfo, bool> where)
        {
            if (self.FullName == null)
                throw new Exception("属性名为空");
            if (_propertyCache.ContainsKey(self.FullName) == false)
            {
                var properties = self.GetProperties().ToList();
                _propertyCache = _propertyCache.Add(self.FullName, properties);
                return properties.Where(where).FirstOrDefault();
            }
            else
            {
                return _propertyCache[self.FullName].Where(where).FirstOrDefault();
            }
        }
        /// <summary>
        /// 获取属性列表 并将 列表属性放入缓存
        /// </summary>
        /// <param name="self"></param>
        /// <returns></returns>
        public static List<PropertyInfo> GetAllProperties(this Type self)
        {
            if (self.FullName == null)
                throw new Exception("属性名为空");
            if (_propertyCache.ContainsKey(self.FullName) == false)
            {
                var properties = self.GetProperties().ToList();
                _propertyCache = _propertyCache.Add(self.FullName, properties);
                return properties;
            }
            else
            {
                return _propertyCache[self.FullName];
            }
        }
        #endregion
    }
}
cylsg/cylsg.utility/cylsg.utility.csproj
New file
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Primitives" Version="8.0.0" />
  </ItemGroup>
</Project>