构建企业级.NET应用:CSLA .NET框架实战指南
为什么需要CSLA .NET?
在现代软件开发中,我们拥有丰富的UI框架(Blazor、MAUI、ASP.NET MVC)和数据访问技术(Entity Framework、Dapper),但业务逻辑往往成为被忽视的中间层。CSLA .NET(Component-based Scalable Logical Architecture)填补了这一空白,为业务逻辑提供标准化家园,确保代码跨平台一致性、可维护性和安全性。
读完本文你将掌握:
- 理解CSLA .NET的核心架构与五层设计模式
- 构建可验证、可追踪的业务实体(Business Object)
- 实现完整的CRUD操作与数据门户(Data Portal)交互
- 应用业务规则引擎进行验证与授权
- 在实际项目中集成CSLA组件的最佳实践
CSLA .NET核心架构
CSLA .NET基于五层架构设计,抽象了不同关注点的分离:
核心组件说明
| 组件 | 作用 | 基类示例 |
|---|---|---|
| 业务实体 | 封装业务逻辑和数据 | BusinessBase<T>, ReadOnlyBase<T> |
| 业务列表 | 管理实体集合 | BusinessListBase<T,C>, ReadOnlyListBase<T,C> |
| 数据门户 | 处理数据访问与远程调用 | DataPortal<T> |
| 规则引擎 | 验证与授权逻辑 | ValidationRule, AuthorizationRule |
| 状态管理 | 跟踪对象状态变化 | IsDirty, IsValid, IsNew |
快速上手:构建第一个业务对象
以下通过创建PersonEdit实体演示CSLA核心功能,完整实现CRUD操作与业务规则验证。
步骤1:环境准备
-
创建解决方案结构(以.NET 8为例):
dotnet new sln -n CslaDemo dotnet new classlib -n BusinessLayer && dotnet sln add BusinessLayer dotnet new classlib -n DataAccessLayer && dotnet sln add DataAccessLayer dotnet new console -n ClientApp && dotnet sln add ClientApp -
添加CSLA依赖:
# 业务层添加CSLA核心包 cd BusinessLayer && dotnet add package Csla --version 8.0.0 # 客户端项目引用业务层 cd ../ClientApp && dotnet add reference ../BusinessLayer
步骤2:实现数据传输对象(DTO)
在DataAccessLayer项目中定义DTO,隔离业务层与数据存储:
// DataAccessLayer/PersonDto.cs
namespace DataAccessLayer;
public class PersonDto
{
public int Id { get; set; }
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
}
步骤3:创建业务实体
业务实体继承BusinessBase<T>,封装属性、规则和数据操作:
// BusinessLayer/PersonEdit.cs
using Csla;
using DataAccessLayer;
using System.ComponentModel.DataAnnotations;
namespace BusinessLayer;
[Serializable]
public class PersonEdit : BusinessBase<PersonEdit>
{
#region 属性定义
// 声明属性元数据(支持数据绑定和状态跟踪)
public static readonly PropertyInfo<int> IdProperty =
RegisterProperty<int>(c => c.Id);
public int Id
{
get => GetProperty(IdProperty);
private set => LoadProperty(IdProperty, value);
}
public static readonly PropertyInfo<string> FirstNameProperty =
RegisterProperty<string>(c => c.FirstName);
[Required(ErrorMessage = "名字不能为空")] // 数据注解规则
public string FirstName
{
get => GetProperty(FirstNameProperty);
set => SetProperty(FirstNameProperty, value);
}
public static readonly PropertyInfo<string> LastNameProperty =
RegisterProperty<string>(c => c.LastName);
[Required(ErrorMessage = "姓氏不能为空")]
public string LastName
{
get => GetProperty(LastNameProperty);
set => SetProperty(LastNameProperty, value);
}
#endregion
#region 数据门户方法(CRUD操作)
// 创建新对象
protected override void DataPortal_Create()
{
var dal = new PersonDal();
var dto = dal.Create();
using (BypassPropertyChecks) // 临时绕过属性检查
{
Id = dto.Id;
FirstName = dto.FirstName;
LastName = dto.LastName;
}
BusinessRules.CheckRules(); // 触发初始规则检查
}
// 获取对象(按ID)
private void DataPortal_Fetch(int id)
{
var dal = new PersonDal();
var dto = dal.GetPerson(id);
using (BypassPropertyChecks)
{
Id = dto.Id;
FirstName = dto.FirstName;
LastName = dto.LastName;
}
}
// 插入新对象
protected override void DataPortal_Insert()
{
var dal = new PersonDal();
using (BypassPropertyChecks)
{
var dto = new PersonDto
{
FirstName = FirstName,
LastName = LastName
};
Id = dal.InsertPerson(dto); // 获取数据库生成的ID
}
}
// 更新对象
protected override void DataPortal_Update()
{
var dal = new PersonDal();
using (BypassPropertyChecks)
{
var dto = new PersonDto
{
Id = Id,
FirstName = FirstName,
LastName = LastName
};
dal.UpdatePerson(dto);
}
}
// 删除对象
private void DataPortal_Delete(int id)
{
var dal = new PersonDal();
dal.DeletePerson(id);
}
#endregion
}
步骤4:实现数据访问层(DAL)
数据访问层隔离业务逻辑与数据源,此处使用内存集合模拟数据库:
// DataAccessLayer/PersonDal.cs
using System.Collections.Generic;
using System.Linq;
namespace DataAccessLayer;
public class PersonDal
{
private static readonly List<PersonDto> _dataStore = new();
public PersonDto Create() => new() { Id = -1 };
public PersonDto GetPerson(int id)
{
var entity = _dataStore.FirstOrDefault(e => e.Id == id);
if (entity == null) throw new KeyNotFoundException("记录不存在");
return entity;
}
public int InsertPerson(PersonDto data)
{
data.Id = _dataStore.Any() ? _dataStore.Max(e => e.Id) + 1 : 1;
_dataStore.Add(data);
return data.Id;
}
public void UpdatePerson(PersonDto data)
{
var entity = GetPerson(data.Id);
entity.FirstName = data.FirstName;
entity.LastName = data.LastName;
}
public void DeletePerson(int id) => _dataStore.Remove(GetPerson(id));
}
步骤5:客户端交互示例
控制台应用演示如何使用数据门户操作业务对象:
// ClientApp/Program.cs
using BusinessLayer;
using Csla;
// 创建新对象
var person = await DataPortal.CreateAsync<PersonEdit>();
Console.Write("输入名字: ");
person.FirstName = Console.ReadLine();
Console.Write("输入姓氏: ");
person.LastName = Console.ReadLine();
// 保存对象(自动判断Insert/Update)
if (person.IsSavable) // 检查业务规则是否通过
{
person = await person.SaveAsync();
Console.WriteLine($"保存成功!ID: {person.Id}");
}
else
{
Console.WriteLine("保存失败:");
foreach (var rule in person.BrokenRulesCollection)
Console.WriteLine($"- {rule.Description}");
}
// 查询并更新
var updatedPerson = await DataPortal.FetchAsync<PersonEdit>(person.Id);
updatedPerson.FirstName = "Updated";
await updatedPerson.SaveAsync();
// 删除对象
await DataPortal.DeleteAsync<PersonEdit>(person.Id);
业务规则引擎深度应用
CSLA规则引擎支持验证规则、授权规则和计算规则,以下是高级用法示例:
自定义验证规则
// 确保姓氏不为"测试"
public static void AddLastNameRule()
{
BusinessRules.AddRule(new LastNameRule(LastNameProperty));
}
public class LastNameRule : ValidationRule
{
public LastNameRule(IPropertyInfo prop) : base(prop) { }
protected override void Execute(IRuleContext context)
{
var lastName = (string)context.InputPropertyValues[PrimaryProperty];
if (lastName == "测试")
context.Results.Add(new RuleResult(
PrimaryProperty, "姓氏不能为'测试'"));
}
}
异步授权规则
// 仅允许管理员修改
protected override void AddAuthorizationRules()
{
AuthorizationRules.AllowWrite(LastNameProperty, "Admin");
// 异步规则示例
AuthorizationRules.AddRule(
new AsyncAuthorizationRule(FirstNameProperty),
AuthorizationActions.WriteProperty);
}
高级特性与最佳实践
1. 状态管理与跟踪
CSLA自动管理对象状态,关键属性包括:
IsNew: 对象是否为新创建(未保存到数据库)IsDirty: 对象是否被修改IsValid: 业务规则是否全部通过IsDeleted: 对象标记为删除
if (person.IsDirty && !person.IsNew)
Console.WriteLine("对象已修改但未保存");
2. 数据门户高级配置
通过配置文件指定数据门户模式(本地/远程):
<!-- appsettings.json -->
{
"Csla": {
"DataPortal": {
"DefaultProxy": "Csla.DataPortalClient.HttpProxy, Csla",
"ServerUrl": "https://api.example.com/dataportal"
}
}
}
3. 跨平台支持
CSLA业务对象可在以下平台无缝运行:
项目实战与性能优化
分层架构改进
实际项目中建议引入依赖注入解耦DAL:
// 使用DI注入DAL
protected override async Task DataPortal_FetchAsync(int id)
{
var dal = ApplicationContext.GetRequiredService<IPersonDal>();
var dto = await dal.GetPersonAsync(id);
// 加载数据...
}
性能优化策略
- 对象缓存:使用
[Cacheable]特性缓存只读对象 - 批量操作:使用
CommandBase实现批量处理 - 延迟加载:通过
Child_DataPortal_Fetch延迟加载子对象 - 数据压缩:配置二进制序列化压缩传输数据
总结与进阶学习
CSLA .NET为业务逻辑提供了标准化、可扩展的实现框架,核心优势包括:
- 关注点分离:清晰划分业务逻辑与数据访问
- 跨平台一致性:一套业务逻辑运行于所有.NET平台
- 内置安全性:完善的授权与状态管理
- 减少样板代码:自动化状态跟踪与数据绑定
进阶资源
- 官方文档:深入理解数据门户与规则引擎
- 示例项目:
Samples/ProjectTracker完整企业级应用 - 性能调优:使用
DataPortalInstrumentation监控性能
通过CSLA .NET,开发者可以将精力集中在业务逻辑本身,而非基础设施代码,构建真正面向业务的.NET应用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



