WitchC.DataAnnotations 1.6.0

dotnet add package WitchC.DataAnnotations --version 1.6.0
                    
NuGet\Install-Package WitchC.DataAnnotations -Version 1.6.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="WitchC.DataAnnotations" Version="1.6.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="WitchC.DataAnnotations" Version="1.6.0" />
                    
Directory.Packages.props
<PackageReference Include="WitchC.DataAnnotations" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add WitchC.DataAnnotations --version 1.6.0
                    
#r "nuget: WitchC.DataAnnotations, 1.6.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package WitchC.DataAnnotations@1.6.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=WitchC.DataAnnotations&version=1.6.0
                    
Install as a Cake Addin
#tool nuget:?package=WitchC.DataAnnotations&version=1.6.0
                    
Install as a Cake Tool

WitchC Framework

╔═══════════════════════════════════════════════════╗
║                W i t c h C  🧙‍♀️                   ║
║            .NET 企业级应用开发框架              ║
║      (Wicked Intelligent .NET Core Framework)    ║
╚═══════════════════════════════════════════════════╝

.NET License Gitee Tests NuGet

📋 项目介绍

WitchC 是一个基于 .NET 8/9/10 的企业级应用开发框架,旨在提供简单、灵活、高效的开发体验。框架采用模块化设计,提供 22 个功能模块13 个扩展方法类,覆盖企业级应用开发的各个方面。

每个模块都是独立的 NuGet 包,可以按需引入,也可以通过元包 WitchC 一键引入全部功能。全部功能完全开源,无任何付费锁定

✨ 特性亮点

  • 🚀 模块化架构 — 22 个模块独立打包,按需引入,轻量灵活
  • 🎯 多目标框架 — 单包同时支持 .NET 8 / 9 / 10
  • 🔄 约定式 DI — 实现 ITransient / IScoped / ISingleton 标记接口即可自动注册
  • 企业级调度 — 完整的 Cron 解析器、宏触发器、重试/超时/并发控制、管理 Dashboard
  • 📢 事件驱动 — 延迟发布、模糊匹配订阅、失败重试、静态门面 MessageCenter
  • 📋 统一返回 — 标准化 API 响应格式、自动包装、分页支持
  • 📦 开箱即用 — 一行 AddWitchC() 启动核心全家桶
  • 🧪 测试驱动 — 83 个单元测试保障质量
  • 📖 中文文档 — 完善的中文注释和文档

🚀 快速开始

安装

# 方式 1:安装元包,一键引入全部 22 个功能模块
dotnet add package WitchC

# 方式 2:按需安装单个模块
dotnet add package WitchC.ExceptionHandler
dotnet add package WitchC.DynamicApi
dotnet add package WitchC.Schedule
dotnet add package WitchC.EventBus

一行启动

var builder = WebApplication.CreateBuilder(args);

// 一行注册核心服务:依赖注入、缓存、数据验证、动态API、
// CORS、事件总线、HTTP、Mapper、Schedule、UnifyResult、操作日志
builder.Services.AddWitchC(options =>
{
    options.EnableCache = true;           // 内存缓存
    options.EnableDataValidation = true;  // 全局数据验证
    options.EnableDynamicApi = true;      // 动态 WebAPI
    options.EnableEventBus = true;        // 事件总线
    options.EnableSchedule = true;        // 定时任务
    // 其余开关:EnableCors / EnableHttp / EnableMapper / EnableUnifyResult / EnableOperationLog
});

var app = builder.Build();

// 全局异常处理(元包不含,需显式启用)
app.UseGlobalExceptionMiddleware();

app.Run();

注意AddWitchC() 聚合的是核心链路服务。JwtEmailSignalRDatabaseAccessor.SqlSugarFileStorageLocalizationWorkerServiceLogging.Serilog、分布式缓存等模块按需单独注册,见下文各模块说明。

模块导航

分类 模块 一句话说明 章节链接
核心 WitchC App 门面、约定式 DI、扩展方法库
Web ExceptionHandler 全局异常处理 + Oops API
Web DataAnnotations 数据验证
Web DynamicApi 零配置动态 WebAPI
Web UnifyResult 统一返回结果
Web Cors CORS 跨域配置
Web Localization 多语言本地化
数据 DatabaseAccessor.SqlSugar SqlSugar ORM 仓储/审计/工作单元
数据 Mapper 对象映射(Mapster)
数据 Cache 缓存抽象(内存/分布式)
数据 IdGeneration 分布式 ID 生成
集成 EventBus 进程内事件总线
集成 Schedule 定时任务调度 + Dashboard
集成 WorkerService 后台任务服务
集成 Http HTTP 远程请求
集成 Email 邮件发送
集成 SignalR WebSocket 即时通讯
安全 Jwt JWT 鉴权
安全 Encryption 加解密工具
安全 Desensitization 数据脱敏
存储 FileStorage 文件存储抽象
日志 Logging / Logging.Serilog 操作日志

📦 模块详解

🧙‍♀️ WitchC(核心包)

作用:框架的中枢。提供 App 静态门面、约定式依赖注入、13 个扩展方法类,以及 AddWitchC() 聚合注册入口。

App 门面类

在任意位置(包括无法注入服务的静态上下文)访问运行时服务:

// 获取配置
var value = App.GetConfig<string>("ConnectionStrings:Default");

// 获取强类型选项
var options = App.GetOptions<JwtOptions>();

// 解析服务(基于根容器)
var service = App.GetService<IUserService>();

// 获取当前 HttpContext
var userId = App.HttpContext?.GetUserId();

// 获取当前线程 ID / 追踪 ID
var traceId = App.GetTraceId();

// 测量执行时间(毫秒)
var elapsed = App.GetExecutionTime(() => DoWork());

适用场景:静态类/扩展方法中需要访问服务时;遗留代码无法走构造函数注入时;需要统一获取请求上下文信息时。

约定式依赖注入

实现标记接口即可自动注册,无需手写 AddScoped<IUserService, UserService>()

// 1. 注册(扫描全部程序集)
builder.Services.AddWitchCDependencyInjection();

// 也可指定程序集
builder.Services.AddWitchCDependencyInjection(typeof(UserService).Assembly);

// 2. 实现标记接口即自动注册
public class UserService : IUserService, ITransient { }   // 瞬态
public class CacheService : ICacheService, ISingleton { } // 单例
public class OrderService : IOrderService, IScoped { }    // 作用域

// 3. 用 [Injection] 精细控制注册行为
[Injection(Pattern = InjectionPatterns.FirstInterface, Order = 10)]
public class MyService : IMyService, ITransient { }

// 跳过自动注册
[Injection(Skip = true)]
public class InternalService : IInternalService, ITransient { }

// 4. 接口多实现时按名称解析
[Injection(Named = "aliyun")]
public class AliyunSmsService : ISmsService, ITransient { }
[Injection(Named = "tencent")]
public class TencentSmsService : ISmsService, ITransient { }

var sms = namedServiceProvider.GetRequiredService<ISmsService>("aliyun");

// 5. 在单例中安全创建作用域
await Scoped.CreateAsync(async (factory, scope) =>
{
    var repo = scope.ServiceProvider.GetService<IUserRepository>();
    await repo.DoWorkAsync();
});

InjectionPatterns 可选值:Self / FirstInterface / SelfWithFirstInterface / ImplementedInterfaces / All

适用场景:中大型项目服务注册量大、不想维护冗长的注册清单时;多实现需要按名称切换时(多租户、多渠道对接)。


🧨 WitchC.ExceptionHandler(异常处理)

作用:提供业务异常体系(BusinessException / FriendlyException)、Oops 抛出 API、错误码枚举元数据和全局异常中间件,让异常返回友好、格式统一。

// 注册全局异常中间件(挂在管道最前面)
app.UseGlobalExceptionMiddleware();

// 或自定义响应逻辑
app.UseGlobalExceptionMiddleware(async (context, result) =>
{
    context.Response.StatusCode = result.StatusCode;
    await context.Response.WriteAsJsonAsync(new { result.ErrorCode, result.Message });
});

// 业务代码中随时抛出友好异常
throw Oops.Oh("用户不存在");                          // 400
throw Oops.Oh(ErrorCodes.NotFound);                   // 错误码枚举(404 语义)
throw Oops.Oh(ErrorCodes.ValidationError, "用户名");   // 带格式化参数
throw Oops.Oh<InvalidOperationException>("非法操作"); // 抛指定异常类型
throw Oops.OhFriendly("余额不足,请充值");             // 友好异常(可对前端直接展示)

// 错误码枚举:用特性标注文案模板
public enum ErrorCodes
{
    [ErrorCodeItemMetadata("用户 {0} 不存在")]
    NotFound = 1002,
}

适用场景:任何 Web API 项目的标配;需要区分"友好异常"(展示给用户)与"系统异常"(记录日志)时;统一错误码规范时。


✅ WitchC.DataAnnotations(数据验证)

作用:基于 DataAnnotations 的模型验证,支持全局过滤器自动校验和手动校验,内置常用正则验证类型。

// 注册全局验证过滤器
builder.Services.AddWitchCDataValidation();

// DTO 上直接使用标准验证特性
public class CreateUserDto
{
    [Required, StringLength(20)]
    public string Name { get; set; }

    [RegularExpression(ValidationTypes.Phone, ErrorMessage = "手机号格式错误")]
    public string Phone { get; set; }
}

// 标记 [NonValidation] 的类/属性跳过验证
[NonValidation]
public class InternalDto { }

// 手动验证(返回结果而不是抛异常)
var (isValid, errors) = DataValidation.TryValidate(dto);
if (!isValid)
    foreach (var error in errors)
        Console.WriteLine($"{error.MemberNames}: {error.ErrorMessage}");

// 手动验证(失败直接抛验证异常)
DataValidation.Validate(dto);

内置 ValidationTypes 常量:PhoneEmailIdCardUrlIPv4Chinese 等常用正则。

适用场景:API 入参校验;导入 Excel/CSV 等批量数据时逐行校验;配置对象启动时自检。


⚡ WitchC.DynamicApi(动态 WebAPI)

作用:让普通服务类零配置变成 API 控制器——不需要继承 ControllerBase、不需要写路由模板,写业务方法即自动暴露为 RESTful 端点。

// 注册
builder.Services.AddWitchCDynamicApi(options =>
{
    options.DefaultRoutePrefix = "api";   // 路由前缀
    options.UseCamelCaseRoute = true;     // kebab-case 路由
});

// 定义:实现 IDynamicApiController 即成为控制器
public interface IUserService : IDynamicApiController
{
    Task<UserDto> GetUser(int userId);      // GET /api/user/get-user?userId=1
    Task<UserDto> CreateUser(CreateUserDto dto); // POST /api/user/create-user
}

public class UserService : IUserService
{
    public Task<UserDto> GetUser(int userId) { ... }
    public Task<UserDto> CreateUser(CreateUserDto dto) { ... }
}

// 排除个别方法/类
[NonDynamicApi]
public Task BackgroundJob() { ... }

适用场景:业务层直接对外提供 API(ApplicationService 模式);减少 Controller 层样板代码;与 DDD 分层架构配合,让应用服务天然成为 API 端点。


📋 WitchC.UnifyResult(统一返回结果)

作用:标准化 API 响应格式(statusCode / succeeded / data / message / traceId),提供控制器扩展方法、自动包装过滤器和静态工厂。

// 注册(自动包装 + RESTful 风格状态码处理)
builder.Services.AddWitchCUnifyResult();

[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
    [HttpGet("{id}")]
    public IActionResult GetUser(int id)
        => Success(new { id, name = "张三" });          // 自动包装

    [HttpGet]
    public IActionResult GetUsers(int pageIndex = 1, int pageSize = 10)
        => Paged(users, total, pageIndex, pageSize);    // 分页包装

    [HttpGet("error")]
    public IActionResult ErrorDemo()
        => Error("余额不足", 400, "BALANCE_INSUFFICIENT");
}

// 非 Controller 场景用静态工厂
var result = UnifyResult.Success(data);
var failed = UnifyResult.Error("系统繁忙");

// 响应格式
// {
//   "statusCode": 200,
//   "succeeded": true,
//   "message": "success",
//   "data": { "id": 1, "name": "张三" },
//   "traceId": "0HN7GK..."
// }

适用场景:前后端分离项目统一响应契约;网关/客户端统一做错误处理与埋点;分页列表接口标准化。


🌐 WitchC.Cors(跨域配置)

作用:一行启用 CORS,支持任意来源/方法/头、凭证、预检缓存等常用配置,默认策略开箱即用。

// 注册
builder.Services.AddWitchCCors(options =>
{
    options.Origins = new[] { "https://www.example.com", "https://admin.example.com" };
    options.AllowAnyMethod = true;
    options.AllowAnyHeader = true;
    options.AllowCredentials = true;       // 允许携带 Cookie
    options.PreflightMaxAge = 86400;       // 预检结果缓存 1 天
});

// 启用
app.UseWitchCCors();

适用场景:前后端分离部署、前端跨域调用 API 时;微服务 BFF 聚合多端来源时。


🌍 WitchC.Localization(多语言)

作用:轻量级多语言支持,内置内存资源管理,支持代码动态注册资源、查询字符串/Cookie 切换文化,提供静态门面 L

// 注册
builder.Services.AddWitchCLocalization(options =>
{
    options.DefaultCulture = "zh-CN";
    options.SupportedCultures = new[] { "zh-CN", "en-US" };
    options.UseQueryCulture = true;   // ?culture=en-US 切换
    options.UseCookieCulture = true;  // Cookie 持久化选择
});

app.UseWitchCLocalization();

// 任意位置取本地化文本(静态门面)
var text = L.Text("Hello");                     // 你好
var text2 = L.Text("Welcome", "张三");           // 欢迎你,张三(带格式化参数)
var text3 = L.Text("Hello", "en-US");           // 指定文化

// 或注入服务使用
public class WelcomeService(ILocalizationService localization)
{
    public string SayHello() => localization.GetString("Hello");
}

适用场景:需要中英双语或多语言界面的系统;错误消息、枚举描述等随用户文化变化的文案。


🗄️ WitchC.DatabaseAccessor.SqlSugar(数据访问)

作用:基于 SqlSugar 的仓储模式封装,带审计字段自动填充、软删除全局过滤、工作单元、CodeFirst 建表与种子数据、分页查询、按年分库。

// 注册(4 种方式任选)
builder.Services.AddSqlSugar(builder.Configuration);            // 读配置节 DefaultConnection
builder.Services.AddSqlSugar("server=.;uid=sa;pwd=xxx;", DbType.SqlServer);
builder.Services.AddSqlSugar(config => config.ConnectionString = "...");

// 实体:实现接口即获得审计与软删除能力
public class User : IEntity, IAuditing, ISoftDelete
{
    [SugarColumn(IsPrimaryKey = true)]
    public long Id { get; set; }
    public string Name { get; set; }
    public DateTime CreatedTime { get; set; }   // 审计:自动填充
    public string CreatedBy { get; set; }
    public bool IsDeleted { get; set; }         // 软删除:查询自动过滤
}

// 仓储操作
public class UserService(ISqlSugarRepository<User> repo)
{
    public Task<List<User>> GetActiveUsers()
        => repo.Entities.Where(u => u.Name.Contains("张")).ToListAsync();
        // ISoftDelete 已自动过滤 IsDeleted == true

    public Task<long> AddUser(User user)
        => repo.InsertReturnIdentityAsync(user);  // 审计字段自动填充
}

// 分页查询
var page = await db.Queryable<User>().ToPagedListAsync(pageIndex: 1, pageSize: 20);
// page.Items / page.TotalCount / page.TotalPages / page.HasNextPages

// CodeFirst:启动时自动建表 + 灌种子数据
using var db = provider.GetRequiredService<ISqlSugarClient>();
db.InitTablesByReflection(typeof(User).Assembly);
db.InitSeedDataByReflection(db, provider, null, typeof(User).Assembly);

// 按年分库(日志类大表场景)
builder.Services.AddYearDatabase(builder.Configuration, typeof(OrderRecord));

适用场景:喜欢 SqlSugar 的语法甜度、又想要仓储抽象和审计/软删除基础设施的团队;报表类大表按年分库存储。


🔄 WitchC.Mapper(对象映射)

作用:基于 Mapster 的对象映射封装,自动扫描自定义映射配置类,一行完成对象转换。

// 注册(自动扫描 IWitchCRegister 实现)
builder.Services.AddWitchCMapper();

// 复杂映射关系集中注册
public class MapperRegister : IWitchCRegister
{
    public void Register(TypeAdapterConfig config)
    {
        config.NewConfig<User, UserDto>()
              .Map(d => d.RoleName, s => s.Role.Name);
    }
}

// 任意对象一行转换
var dto = user.MapTo<UserDto>();
var dtos = users.MapTo<List<UserDto>>();

适用场景:Entity → DTO 转换;导入/导出模型与领域模型互转;任何"同构对象拷贝"场景。


⚡ WitchC.Cache(缓存)

作用:统一缓存抽象 ICacheService,一套 API 切换内存缓存与分布式缓存,自带 GetOrSetAsync 防击穿模式。

// 内存缓存(单机)
builder.Services.AddWitchCMemoryCache();

// 分布式缓存(基于 IDistributedCache,接 Redis 时换这一行即可)
builder.Services.AddWitchCDistributedCache();

public class UserService(ICacheService cache)
{
    // 读缓存,不存在则执行工厂并回填
    public Task<UserDto?> GetUserAsync(long id)
        => cache.GetOrSetAsync($"user:{id}",
            () => GetUserFromDbAsync(id),
            expiration: TimeSpan.FromMinutes(30));

    public Task RemoveCacheAsync(long id) => cache.RemoveAsync($"user:{id}");
}

适用场景:热点数据缓存、配置缓存;单机起步、后期平滑迁到 Redis 的项目。


🆔 WitchC.IdGeneration(ID 生成)

作用:分布式 ID 生成器:雪花 ID(含 WorkerId 自动分配)、有序 GUID、带前缀短 ID、时间戳 ID。纯静态工具,无需注册。

// 雪花 ID(趋势递增 long,适合做主键/订单号基数)
long id = IdGenerator.NextSnowflakeId();
string idStr = IdGenerator.NextSnowflakeIdString();

// WorkerId 自动分配:环境变量 SNOWFLAKE_WORKER_ID > 机器名哈希
IdGenerator.InitializeWorkerId();   // 建议启动时调用一次

// 有序 GUID(适合 MySQL 聚簇索引,避免随机 GUID 页分裂)
Guid guid = IdGenerator.NextSequentialGuid();

// 业务单号:带前缀短 ID / 时间戳 ID
string orderNo = IdGenerator.NextPrefixedId("ORD");     // ORD000001
string logNo = IdGenerator.NextTimestampId("LOG");      // LOG20260823120000001

适用场景:分库分表下的全局唯一主键;订单号/流水号生成;高频插入表的索引友好主键。


📢 WitchC.EventBus(事件总线)

作用:进程内事件总线,基于 Channel 的异步解耦。支持类型安全订阅、事件 ID 字符串订阅、模糊匹配、延迟发布、失败重试、降级策略和静态门面 MessageCenter

// 注册(自动扫描 IEventHandler<T> 实现)
builder.Services.AddWitchCEventBus(options =>
{
    options.MaxConcurrency = 10;          // 最大并发
    options.EnableFuzzyMatch = true;      // 启用正则模糊匹配
    options.DefaultNumRetries = 2;        // 默认重试次数
    options.DefaultRetryTimeout = 1000;   // 重试间隔 ms
});

// 方式 1:强类型事件(实现 IEvent + IEventHandler<T> 自动订阅)
public class UserCreatedEvent : IEvent { public long UserId { get; set; } }

public class SendWelcomeEmailHandler : IEventHandler<UserCreatedEvent>
{
    public Task HandleAsync(UserCreatedEvent @event, CancellationToken ct)
        => SendEmailAsync(@event.UserId);
}

await eventBus.PublishAsync(new UserCreatedEvent { UserId = 123 });

// 方式 2:字符串事件 ID + 模糊匹配订阅
eventBus.Subscribe("user.*", async (source, ct) =>
{
    Console.WriteLine($"收到事件 {source.EventId}, 载荷 {source.Payload}");
});
await eventBus.PublishAsync("user.login", new { UserId = 123 });

// 方式 3:特性订阅(含重试与降级配置)
public class OrderHandlers
{
    [EventSubscribe("order.paid", NumRetries = 3, RetryTimeout = 2000)]
    public Task OnOrderPaid(EventSource source, CancellationToken ct) { ... }
}

// 延迟发布(订单超时取消的经典用法)
await eventBus.PublishDelayAsync(new OrderTimeoutEvent { OrderId = 456 },
    TimeSpan.FromMinutes(30));

// 静态门面:无法注入 IEventBus 的地方直接调用
await MessageCenter.PublishAsync(new NotificationEvent { Message = "Hello" });

适用场景:注册后置动作(发欢迎邮件、记积分);订单超时/重试类延迟任务(免 Redis);模块间解耦,避免服务互相直调。


⏰ WitchC.Schedule(定时任务)

作用:企业级作业调度:内置完整 Cron 解析器(无 Quartz 依赖)、8 种宏触发器、特性声明式作业、流式 JobBuilder、运行时动态管理 API(IScheduler)和 HTML 管理面板。

// 注册调度器(后台服务自动启动)
builder.Services.AddWitchCSchedule(options =>
{
    options.MaxConcurrency = 10;
    options.DefaultMaxRetries = 2;
});

// 方式 1:Cron 表达式 + Lambda
builder.Services.AddScheduledJob("daily-cleanup", "0 2 * * *",
    async (context, ct) => await CleanupAsync());

// 方式 2:宏触发器(免写 Cron)
builder.Services.AddScheduledJob("heartbeat", MacroTriggerType.Minutely,
    async (context, ct) => await HeartbeatAsync());
// 宏类型:Secondly / Minutely / Hourly / Daily / Weekly / Monthly / Yearly / Workday

// 方式 3:IJob 实现类 + 流式配置
public class SyncJob : IJob
{
    public Task ExecuteAsync(JobExecutionContext context, CancellationToken ct)
        => SyncDataAsync();
}

builder.Services.AddScheduledJob<SyncJob>(builder => builder
    .WithName("data-sync")
    .WithCron("*/5 * * * *")                  // 或 .WithMacro / .WithPeriod
    .WithRetry(3, 2000)                       // 失败重试 3 次,间隔 2s
    .WithTimeout(TimeSpan.FromMinutes(5))     // 单次执行超时
    .WithConcurrent(false));                  // 禁止并发执行

// 方式 4:特性声明式(自动发现)
[Cron("0 3 * * *")]
public class NightlyReportJob : IJob { ... }

// 运行时动态管理
var scheduler = provider.GetRequiredService<IScheduler>();
await scheduler.PauseJob(jobId);
await scheduler.TriggerJob(jobId);            // 手动触发一次
var history = scheduler.GetExecutionHistory(jobId, count: 10);

// 管理面板(HTML + JSON API)
app.UseScheduleDashboard("/schedule");

适用场景:日报表生成、数据同步、缓存预热等周期任务;夜间批处理;需要在运行时暂停/恢复/手动触发作业的运营型系统。


🔁 WitchC.WorkerService(后台任务)

作用:简化 ASP.NET Core BackgroundService 的编写:周期执行、启动延迟、并发控制、错误续跑,一个委托即可注册后台任务。

// 方式 1:委托式(最快)
builder.Services.AddWitchCWorker(
    async ct => await RefreshTokenCacheAsync(ct),
    options => { options.IntervalSeconds = 60; });

// 方式 2:类式(继承 WitchCBackgroundService)
public class HealthCheckWorker : WitchCBackgroundService
{
    protected override int IntervalSeconds => 30;
    protected override Task ExecuteTaskAsync(CancellationToken ct)
        => CheckHealthAsync(ct);
}
builder.Services.AddWitchCWorker<HealthCheckWorker>();

// WorkerOptions:IntervalSeconds / StartupDelaySeconds / ExecuteOnStartup
//                / MaxConcurrency / ContinueOnError

适用场景:轻量周期任务(缓存刷新、心跳上报),不需要 Cron 那么复杂的调度语义时;相比 Schedule 模块更轻、无调度器概念。


🌐 WitchC.Http(HTTP 远程请求)

作用:类型安全、链式调用的 HTTP 客户端封装,基于 IHttpClientFactory,内置重试、默认超时、默认请求头配置。

// 注册(可选:全局默认值)
builder.Services.AddWitchCHttp(options =>
{
    options.BaseAddress = "https://api.example.com";
    options.TimeoutSeconds = 30;
    options.RetryCount = 3;              // 请求失败自动重试
    options.RetryDelayMilliseconds = 1000;
});

// 链式调用
public class UserService(HttpService http)
{
    public Task<UserDto?> GetUserAsync(string token)
        => http.Get("https://api.example.com/users/1")
               .WithBearerToken(token)
               .WithTimeout(TimeSpan.FromSeconds(10))
               .SendAsAsync<UserDto>();

    public Task<CreateResult?> CreateUserAsync()
        => http.Post("https://api.example.com/users")
               .WithJsonBody(new { Name = "张三", Age = 25 })
               .SendAsAsync<CreateResult>();
}
// 可用谓词:Get / Post / Put / Delete / Patch
// 可用修饰:AddHeader / WithJsonBody / WithStringBody / WithFormBody
//           WithTimeout / WithBearerToken / WithBasicAuth
// 发送方法:SendAsStringAsync / SendAsAsync<T> / SendAsync(HttpResponseMessage)

适用场景:调用第三方开放平台(支付、短信、OAuth);微服务间 HTTP 调用;需要统一重试与超时策略的出站请求。


📧 WitchC.Email(邮件发送)

作用:基于 MailKit 的邮件服务封装,支持简单邮件、HTML、附件和 {{占位符}} 模板渲染。

// 注册
builder.Services.AddWitchCEmail(options =>
{
    options.SmtpServer = "smtp.example.com";
    options.SmtpPort = 587;
    options.UseSsl = true;
    options.Username = "noreply@example.com";
    options.Password = "***";
    options.SenderName = "WitchC 系统";
});
// 也可从配置节读取:AddWitchCEmail("Email")

public class NoticeService(IEmailService email)
{
    // 简单邮件
    public Task SendWelcomeAsync()
        => email.SendSimpleAsync("user@example.com", "欢迎注册", "你好!", isHtml: false);

    // 模板邮件({{Name}} 占位符自动替换)
    public Task SendTemplateAsync()
        => email.SendTemplateAsync("user@example.com", "账单通知",
            "您好 {{Name}},本月账单 {{Amount}} 元", new { Name = "张三", Amount = 99 });
}

// 复杂邮件(附件 + HTML)
var message = new EmailMessage
{
    To = { "boss@example.com" },
    Subject = "月度报表",
    HtmlBody = "<p>请查收附件</p>",
    Attachments = { await EmailAttachment.FromFileAsync("report.pdf") }
};
await emailService.SendAsync(message);

适用场景:注册验证邮件、账单通知、运营报表定时推送。


📡 WitchC.SignalR(即时通讯)

作用:SignalR 封装——内置 MessageHub / NotificationHub 与服务端推送服务 ISignalRMessageService,一行映射端点,统一 Hub 配置。

// 注册 + 映射
builder.Services.AddWitchCSignalR(options =>
{
    options.HubPrefix = "/hubs";
    options.EnableDetailedErrors = false;
});

app.MapWitchCHubs();   // 自动映射 /hubs/message 与 /hubs/notification

// 服务端任意位置推送
public class NoticeService(ISignalRMessageService signalR)
{
    public Task PushToUserAsync(string userId, string message)
        => signalR.SendToUserAsync(userId, "receiveMessage", message);

    public Task PushToGroupAsync(string groupName, string message)
        => signalR.SendToGroupAsync(groupName, "receiveMessage", message);
}

// 客户端直接调用 Hub 方法(MessageHub 内置)
// connection.invoke("SendToAll", message)
// connection.invoke("JoinGroup", groupName)

// 自定义 Hub 也可映射
app.MapHub<ChatHub>("/hubs/chat");

适用场景:站内消息/系统通知;多人协作(白板、协同编辑);服务端主动推送(监控大屏、进度条)。


🔐 WitchC.Jwt(JWT 鉴权)

作用:一站式 JWT 方案:注册即同时配置 JwtBearer 认证 + 令牌服务(签发/校验/刷新),支持从配置节读取。

// 注册(自动完成 AddAuthentication().AddJwtBearer())
builder.Services.AddWitchCJwt(options =>
{
    options.SecretKey = "your-secret-key-at-least-32-chars!!"; // 至少 32 字符
    options.Issuer = "MyApp";
    options.Audience = "MyApp";
    options.AccessTokenExpiration = 30;   // 分钟
    options.RefreshTokenExpiration = 7;   // 天
});

app.UseAuthentication();
app.UseAuthorization();

// 登录签发令牌
public class AuthService(JwtTokenService jwt)
{
    public LoginResult Login(User user)
    {
        var claims = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new Claim(ClaimTypes.Name, user.Name)
        };
        return new LoginResult
        {
            AccessToken = jwt.GenerateAccessToken(claims),
            RefreshToken = jwt.GenerateRefreshToken(),
            ExpiresAt = jwt.GetExpiration(jwt.GenerateAccessToken(claims))
        };
    }

    public ClaimsPrincipal? Validate(string token)
        => jwt.GetPrincipalFromToken(token);
}

适用场景:前后端分离/小程序登录鉴权;需要 AccessToken + RefreshToken 双令牌机制的项目。


🔒 WitchC.Encryption(加解密工具)

作用:纯静态加密工具类 Encrypt,覆盖哈希、HMAC、Base64/Base64Url、AES 对称加解密、随机数。无需注册服务。

// 哈希(密码存储、文件校验)
string md5 = Encrypt.Md5("abc");                          // 32 位小写
string sha256 = Encrypt.Sha256("abc");
string hmac = Encrypt.HmacSha256("payload", "secret-key"); // API 签名

// Base64(含 URL 安全变体,适合放 token/查询参数)
string b64 = Encrypt.Base64UrlEncode(data);

// AES 对称加解密(配置加密、敏感字段加密)
string cipher = Encrypt.AesEncrypt("secret-text", key32Bytes, iv);
string plain = Encrypt.AesDecrypt(cipher, key32Bytes, iv);

// 随机数(验证码、盐值、密钥)
string code = Encrypt.RandomString(6);
byte[] salt = Encrypt.RandomBytes(16);

适用场景:密码哈希与盐值;第三方 API 请求签名(HMAC);配置项/数据库敏感字段加解密;短信验证码生成。


🕶️ WitchC.Desensitization(数据脱敏)

作用:纯静态工具类 Desensitize,对手机号、身份证、邮箱、姓名、银行卡、地址、车牌做掩码处理,支持复姓。

Desensitize.Phone("13812345678");      // 138****5678
Desensitize.IdCard("110101199001011234"); // 1101**********1234
Desensitize.Email("zhangsan@qq.com");  // zha***@qq.com
Desensitize.Name("张三");               // 张*(复姓"欧阳锋" → "欧**")
Desensitize.BankCard("6222021234567890123"); // 6222***********0123
Desensitize.Address("广西南宁市青秀区XX路XX号", 6); // 保留前 6 位
Desensitize.PlateNumber("桂A12345");    // 桂A***45

适用场景:日志打印用户信息前脱敏;客服后台展示个人隐私数据;接口对第三方返回时的合规处理(个保法要求)。


📁 WitchC.FileStorage(文件存储)

作用:文件存储抽象接口 IFileStorage + 默认本地存储实现,统一上传/下载/删除/列举/URL 生成,IFormFile 直接保存扩展,未来可无缝替换为 OSS/MinIO 实现。

// 注册(默认本地存储,可指定根目录)
builder.Services.AddWitchCFileStorage(options =>
{
    options.RootPath = "uploads";
});

public class AvatarController(IFileStorage fileStorage)
{
    // 单文件上传
    public async Task<FileStorageResult> Upload(IFormFile file)
        => await fileStorage.SaveFileAsync(file);

    // 批量上传
    public Task<IEnumerable<FileStorageResult>> UploadMany(List<IFormFile> files)
        => fileStorage.SaveFilesAsync(files);

    // 下载 / 删除 / 列举
    public Task<Stream?> Download(string path) => fileStorage.DownloadAsync(path);
    public Task<bool> Delete(string path) => fileStorage.DeleteAsync(path);
    public Task<IEnumerable<FileInfo>> List(string dir)
        => fileStorage.ListFilesAsync(dir, searchPattern: "*.png");

    // 拿到可访问 URL
    public string Url(string path) => fileStorage.GetUrl(path);
}

适用场景:头像/附件上传下载;本地起步、将来迁云的对象存储场景(只换实现不换业务代码)。


📝 WitchC.Logging + WitchC.Logging.Serilog(操作日志)

作用:操作日志模块——[OperationLog] 特性标记在方法上,自动记录操作人、请求路径、IP、耗时、状态码;默认存内存,Serilog 集成包可写入任意 Sink。

// 注册(默认内存实现,适合演示/测试)
builder.Services.AddWitchCOperationLog();

// 或自定义存储(实现 IOperationLogService)
builder.Services.AddWitchCOperationLog<DatabaseOperationLogService>();

// 或写入 Serilog(文件/ES/Seq 等任意 Sink)
builder.Services.AddWitchCOperationLogSerilog();

// 标记即记录
[OperationLog("用户登录", Description = "后台登录", LogRequestParams = true)]
public async Task<LoginResult> Login(LoginDto dto) { ... }

// 查询审计记录
public Task<List<OperationLog>> Query(IOperationLogService log)
    => log.QueryAsync(userId: "1001", operation: "用户登录",
                      startTime: DateTime.Today, pageIndex: 1, pageSize: 20);

适用场景:后台管理系统操作审计(谁在什么时候改了什么);敏感操作留痕(删除、导出、资金变动)。


🛠️ 扩展方法库

核心包 WitchC 内置 13 个扩展方法类(命名空间 WitchC.Extensions),开箱即用:

扩展类 代表方法 说明
TaskExtensions WithTimeout, RetryAsync, FireAndForget 任务超时控制、失败重试、后台"发射后不管"
TypeExtensions IsNullable, IsNumeric, IsSimpleType, GetFriendlyName, HasImplemented 类型判断与反射辅助
EnumExtensions GetDescription, GetDisplayName 读取枚举的 Description/DisplayName 特性
JsonExtensions ToJson, FromJson, IsValidJson JSON 序列化(默认 CamelCase + 忽略 null)
LinqExpressionExtensions And, Or, Not, GetPropertyName 表达式树动态组合(查询条件拼接利器)
HttpContextExtensions GetUserId, GetUserName, GetRoles, GetClientIp, IsAjaxRequest 从请求上下文提取用户信息
GuidExtensions ToShortString, ToBase64, FromBase64, NewSequentialGuid, IsEmpty Guid 压缩与格式互转
StreamExtensions ToByteArray, ToStream, SaveToFileAsync, ComputeMd5, ComputeSha256 流操作与哈希计算
CollectionExtensions ForEach, Batch, Shuffle, Random, ToTree, ElementAtOrDefault 集合分批/乱序/树形化
DictionaryExtensions GetOrDefault, GetOrAdd, Merge, ToQueryString, ToConcurrentDictionary 字典安全读写
DateTimeExtensions StartOfDay, EndOfMonth, StartOfWeek, IsBetween 日期边界与区间判断
StringExtensions IsNullOrEmpty, Truncate, ToCamelCase, IsEmail 字符串常用操作
ObjectExtensions DeepClone, ToDictionary, SafeToString, IsNumeric 对象深拷贝与安全转换
// 几个高频用法
var batches = orders.Batch(500);                       // 分批处理,防内存爆
var tree = departments.ToTree(d => d.Id, d => d.ParentId); // 平面列表转树
var condition = nameExpr.And(ageExpr);                 // 动态拼接查询条件
var url = dict.ToQueryString();                        // {"a":1} -> "a=1&b=2"
await task.RetryAsync(3);                              // 失败重试 3 次
var userJson = user.ToJson(indented: true);            // 格式化 JSON

说明:与 .NET 6+ 内置 LININ 重复的方法(如 DistinctByToHashSet)框架不再重复提供,避免调用二义性,直接使用内置版本即可。


📁 项目结构

WitchC/
├── framework/                              # 框架源码(23 个项目)
│   ├── WitchC.sln                          # 框架解决方案
│   ├── Directory.Build.props               # 全局构建属性(统一版本 1.6.0)
│   ├── WitchC/                             # 核心包:App / DI / 13 个扩展类
│   ├── WitchC.ExceptionHandler/            # 异常处理
│   ├── WitchC.DataAnnotations/             # 数据验证
│   ├── WitchC.DynamicApi/                  # 动态 WebAPI
│   ├── WitchC.UnifyResult/                 # 统一返回结果
│   ├── WitchC.Cors/                        # 跨域配置
│   ├── WitchC.Localization/                # 多语言
│   ├── WitchC.DatabaseAccessor.SqlSugar/   # 数据访问(仓储/审计/软删除/工作单元)
│   ├── WitchC.Mapper/                      # 对象映射
│   ├── WitchC.Cache/                       # 缓存抽象
│   ├── WitchC.IdGeneration/                # ID 生成
│   ├── WitchC.EventBus/                    # 事件总线
│   ├── WitchC.Schedule/                    # 定时任务(Cron/宏触发器/Dashboard)
│   ├── WitchC.WorkerService/               # 后台任务
│   ├── WitchC.Http/                        # HTTP 远程请求
│   ├── WitchC.Email/                       # 邮件发送
│   ├── WitchC.SignalR/                     # 即时通讯
│   ├── WitchC.Jwt/                         # JWT 鉴权
│   ├── WitchC.Encryption/                  # 加解密工具
│   ├── WitchC.Desensitization/             # 数据脱敏
│   ├── WitchC.FileStorage/                 # 文件存储
│   ├── WitchC.Logging/                     # 操作日志
│   └── WitchC.Logging.Serilog/             # 操作日志 Serilog 集成
├── tests/
│   └── WitchC.Tests/                       # 83 个单元测试
├── templates/                              # dotnet new 项目模板
├── samples/
│   └── witchc-web-api/                     # RBAC 示例(DDD 架构 + Aspire)
└── nupkgs/                                 # NuGet 包输出(nupkg + snupkg)

🔧 技术栈

技术 用途
.NET 8 / 9 / 10 运行时(单包多目标)
ASP.NET Core Web 框架
SqlSugar ORM(数据访问模块)
Mapster 对象映射
MailKit / MimeKit 邮件发送
SignalR 即时通讯
System.IdentityModel.Tokens.Jwt JWT 鉴权
xUnit / Moq 单元测试

🧪 测试

# 框架独立测试项目(Cron 解析、触发器、作业、事件总线、约定式 DI、UnifyResult 等,83 个测试)
dotnet test tests/WitchC.Tests/

# RBAC 示例的业务单元测试(61 个)
dotnet test samples/witchc-web-api/WitchC.RBAC.UnitTests/

# 运行特定测试类
dotnet test tests/WitchC.Tests --filter "FullyQualifiedName~CronExpressionTests"
测试项目 覆盖内容 测试数 状态
tests/WitchC.Tests Cron 解析、触发器、作业调度、事件总线、约定式 DI、UnifyResult 83 ✅ 全部通过
samples/.../RBAC.UnitTests RBAC 示例业务逻辑 61 ✅ 全部通过

🎯 路线图

v1.0 ~ v1.5(已完成)

  • 22 个功能模块 + 13 个扩展方法库
  • 定时任务增强(Cron 解析器 / 宏触发器 / Dashboard)
  • 事件总线增强(延迟发布 / 模糊匹配 / 重试)
  • 多目标 .NET 8 / 9 / 10
  • 83 个单元测试 + RBAC DDD 示例

v1.6(规划中)

  • 老模块测试补齐(Encryption / Desensitization / IdGeneration / FileStorage)
  • 按年分库文档与示例
  • 可选云存储实现(OSS / MinIO)

v2.0(远景)

  • 分布式事件总线(RabbitMQ / Kafka 适配)
  • 分布式事务
  • API 网关
  • 微服务支持与云原生适配

🤝 贡献指南

  1. Fork 项目
  2. 创建功能分支 (git checkout -b feature/amazing-feature)
  3. 提交更改 (git commit -m 'Add some amazing feature')
  4. 推送到分支 (git push origin feature/amazing-feature)
  5. 开启 Pull Request

📄 许可证

本项目采用 Apache 2.0 许可证 - 查看 LICENSE 文件了解详情


📞 支持与联系


🙏 致谢

感谢以下开源项目:


╔═══════════════════════════════════════════════════╗
║   感谢使用 WitchC 框架!让我们一起创造魔法!   ║
║   Let's make some magic with .NET! ✨             ║
╚═══════════════════════════════════════════════════╝

最后更新: 2026年8月

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on WitchC.DataAnnotations:

Package Downloads
WitchC

WitchC 企业级应用开发框架 - 一键引入全部功能模块(聚合包,也可按需单独安装子模块)

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.6.0 111 8/30/2026
1.5.3 112 8/30/2026
1.5.2 109 8/23/2026
1.4.0 102 8/22/2026
1.2.0 119 6/29/2026