WitchC.DataAnnotations
1.6.0
dotnet add package WitchC.DataAnnotations --version 1.6.0
NuGet\Install-Package WitchC.DataAnnotations -Version 1.6.0
<PackageReference Include="WitchC.DataAnnotations" Version="1.6.0" />
<PackageVersion Include="WitchC.DataAnnotations" Version="1.6.0" />
<PackageReference Include="WitchC.DataAnnotations" />
paket add WitchC.DataAnnotations --version 1.6.0
#r "nuget: WitchC.DataAnnotations, 1.6.0"
#:package WitchC.DataAnnotations@1.6.0
#addin nuget:?package=WitchC.DataAnnotations&version=1.6.0
#tool nuget:?package=WitchC.DataAnnotations&version=1.6.0
WitchC Framework
╔═══════════════════════════════════════════════════╗
║ W i t c h C 🧙♀️ ║
║ .NET 企业级应用开发框架 ║
║ (Wicked Intelligent .NET Core Framework) ║
╚═══════════════════════════════════════════════════╝
📋 项目介绍
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()聚合的是核心链路服务。Jwt、SignalR、DatabaseAccessor.SqlSugar、FileStorage、Localization、WorkerService、Logging.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 远程请求 | → |
| 集成 | 邮件发送 | → | |
| 集成 | 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 常量:Phone、Email、IdCard、Url、IPv4、Chinese 等常用正则。
适用场景: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 重复的方法(如
DistinctBy、ToHashSet)框架不再重复提供,避免调用二义性,直接使用内置版本即可。
📁 项目结构
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 网关
- 微服务支持与云原生适配
🤝 贡献指南
- Fork 项目
- 创建功能分支 (
git checkout -b feature/amazing-feature) - 提交更改 (
git commit -m 'Add some amazing feature') - 推送到分支 (
git push origin feature/amazing-feature) - 开启 Pull Request
📄 许可证
本项目采用 Apache 2.0 许可证 - 查看 LICENSE 文件了解详情
📞 支持与联系
- 🐙 Gitee: https://gitee.com/ingkele/WitchC
- 📧 邮箱: 598792849@qq.com
🙏 致谢
感谢以下开源项目:
╔═══════════════════════════════════════════════════╗
║ 感谢使用 WitchC 框架!让我们一起创造魔法! ║
║ Let's make some magic with .NET! ✨ ║
╚═══════════════════════════════════════════════════╝
最后更新: 2026年8月
| Product | Versions 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. |
-
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.