基础设施分层
FreeKitModules 采用 DDD 分层架构,按职责划分为多个层次。
DDD 分层
src/Services/
├── Domain/ # 领域层:实体、值对象、领域服务
├── Application/ # 应用层:用例编排、DTO
├── Controllers/ # API 层:控制器、路由
├── Contracts/ # 契约层:接口定义
├── Models/ # 模型层:数据模型
├── Repositories/ # 仓储层:数据访问
├── Data/ # 数据层:DbContext
├── Hubs/ # 通信层:SignalR Hub
├── Runtime/ # 运行时:配置绑定
└── *ModuleStartup.cs # 模块启动类
各层职责
Domain(领域层)
领域层包含业务逻辑的核心。
// 实体
public class Article : FullAuditEntity<Guid, Guid>, ITenant
{
public Guid? TenantId { get; set; }
public string Title { get; set; } = default!;
public string Content { get; set; } = default!;
// 领域方法
public void Publish()
{
if (string.IsNullOrEmpty(Title))
throw new BusinessException("Title is required");
AddDomainEvent(new ArticlePublishedEvent(Id));
}
}
// 值对象
public record Money(decimal Amount, string Currency);
// 领域服务
public class ArticleDomainService : IArticleDomainService
{
public void PublishArticle(Article article)
{
article.Publish();
}
}
Application(应用层)
应用层编排用例,协调领域服务。
// 应用服务
public class ArticleService : IArticleService, IScopedDependency
{
private readonly IArticleRepository _articleRepository;
private readonly IUnitOfWork _unitOfWork;
public async Task<ArticleDto> CreateAsync(CreateArticleRequest request)
{
var article = new Article
{
Title = request.Title,
Content = request.Content
};
await _articleRepository.InsertAsync(article);
await _unitOfWork.SaveChangesAsync();
return new ArticleDto
{
Id = article.Id,
Title = article.Title
};
}
}
Controllers(API 层)
API 层提供 HTTP 接口。
[ApiController]
[Route("api/[module]/[controller]")]
public class ArticleController : FreeKitController
{
private readonly IArticleService _articleService;
public ArticleController(IArticleService articleService)
{
_articleService = articleService;
}
[HttpGet("{id}")]
public async Task<ArticleDto> GetById(Guid id)
{
return await _articleService.GetByIdAsync(id);
}
[HttpPost]
[Authorize]
public async Task<ArticleDto> Create(CreateArticleRequest request)
{
return await _articleService.CreateAsync(request);
}
}
Contracts(契约层)
契约层定义接口和常量。
// 服务接口
public interface IArticleService
{
Task<ArticleDto> GetByIdAsync(Guid id);
Task<ArticleDto> CreateAsync(CreateArticleRequest request);
}
// 权限定义
public static class CmsKitPermissions
{
public static class Articles
{
public const string Default = GroupName + ".Articles";
public const string Create = Default + ".Create";
public const string Update = Default + ".Update";
public const string Delete = Default + ".Delete";
}
}
Repositories(仓储层)
仓储层封装数据访问。
public class ArticleRepository : IArticleRepository
{
private readonly IFreeSql _fsql;
public ArticleRepository(IFreeSql fsql)
{
_fsql = fsql;
}
public async Task<Article> GetByIdAsync(Guid id)
{
return await _fsql.Select<Article>().Where(a => a.Id == id).FirstAsync();
}
public async Task InsertAsync(Article article)
{
await _fsql.InsertAsync(article).ExecuteAffrowsAsync();
}
}
模块结构示例
Identity 模块
FreeKit.Identity/
├── Domain/
│ ├── Identity/ # 用户/角色 Manager
│ ├── Captcha/ # 验证码
│ ├── Device/ # 设备管理
│ └── Permissions/ # 权限
├── Application/
│ ├── Account/ # 账户管理
│ ├── Users/ # 用户管理
│ ├── Roles/ # 角色管理
│ └── ...
├── Controllers/ # 22 个 API 控制器
├── Models/ # 实体定义
├── Contracts/ # 权限定义
├── Repositories/ # 仓储实现
└── IdentityModuleStartup.cs
CmsKit 模块
FreeKit.CmsKit/
├── Domain/
│ ├── Articles/ # 文章
│ ├── Comments/ # 评论
│ ├── Polls/ # 投票
│ └── ...
├── Application/
│ ├── Content/ # 内容管理
│ ├── Engagement/ # 互动
│ └── ...
├── Controllers/ # 30+ 个 API 控制器
├── Models/ # 实体定义
├── Contracts/ # 权限定义
└── CmsKitModuleStartup.cs
实体基类
// 主键
public class Entity<TKey>
{
public TKey Id { get; set; }
}
// 审计
public class FullAuditEntity<TKey, TUserKey> : Entity<TKey>
{
public TUserKey CreateUserId { get; set; }
public string CreateUserName { get; set; }
public DateTime CreateTime { get; set; }
public TUserKey UpdateUserId { get; set; }
public string UpdateUserName { get; set; }
public DateTime? UpdateTime { get; set; }
public TUserKey DeleteUserId { get; set; }
public string DeleteUserName { get; set; }
public DateTime? DeleteTime { get; set; }
public bool IsDeleted { get; set; }
}
// 软删除
public interface ISoftDelete
{
bool IsDeleted { get; set; }
}
// 租户
public interface ITenant
{
Guid? TenantId { get; set; }
}
依赖注入
服务标记接口
| 接口 | 生命周期 | 说明 |
|---|---|---|
IScopedDependency | 每次请求 | 默认选择 |
ITransientDependency | 瞬时 | 无状态服务 |
ISingletonDependency | 单例 | 缓存、配置 |
Autofac 注册
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>((_, cb) =>
{
cb.RegisterModule(new FreeKitModule([typeof(Program).Assembly]));
cb.RegisterModule(new UnitOfWorkModule([typeof(Program).Assembly]));
});