Rockford 创建的CSLA.Net 框架,提供了创建业务对象的架构。在该框架中,不管是在Windows Forms 或 Web应用程序,可以在任何地方、任何时间创建和存储对象。除了保持一致的客户端行为,CSLA 保持对后台数据库访问的透明,不管是基于Web services、.Net Remoting或 .Net Enterprise Services的网络协议。最后,该框架提供了内置的功能,减轻企业级应用程序的通用功能开发。例如,CSLA 可让你轻松实现对对象属性的roles-based 读写访问权限;应用业务规则验证;通过仅仅保存副对象,实现对子对象的保存。 本文通过一些C# 代码来演示CSLA 的一些基本概念。CSLA 大量使用了工厂设计模式,因此你可以完全理解这一模式的操作。 CSLA框架的基本原则 – 适用于分布式应用的框架,提供了一组基类,你可继承基类,编写业务对象来实现应用程序领域的需求。为了清晰理解 CSLA,你需要理解两个核心概念:1. CSLA 实现了工厂设计模式(Factory Design Pattern);2. CSLA DataPortal 的本质和使用。 理解CSLA 和工厂模式(Factory Pattern) CSLA 使用Factory Pattern,允许框架创建非常强大的业务对象,因此大量对象的构建对开发人员来说是不可见的。使用Factory Pattern,你从不直接 new 一个对象。而是要求对象的 Factory 来创建,Factory 对象提供了调用方法。 Mr. Lhotka 在CSLA 使用了不同的factory pattern,称为class-in-charge。在该模式中,工厂对象的构造器定义为 private,创建方法定义为static,并生成对象实例。下图演示了工厂设计模式class-in-charge 的概念。 下面的代码来自Music Catalog 范例程序,该范例程序演示了CSLA如何使用factory pattern 构建对象,并返回实例。此外,范例代码演示了CSLA 数据管理的内部机制。 CSLA 中factory pattern的使用
/*****************************************
* 调用 static GetCatalog(string countryOfBand) 方法返回Catalog对象实例
* Catalog 对象有Bands属性,是Band 对象集合。
******************************************/
Catalog catalog = Catalog.GetCatalog(“USA”);
BandsList bands = catalog.Bands;
使用 DataPortal 任何企业级架构的核心是获取和存储数据的能力。CSLA 实现了一种管理数据的方法,甚至不必知道数据库的位置,或使用的网络协议,就可以编写存储和读取数据库的代码。此外,CSLA 可让你修改数据源或网络协议,而不必更新源代码。 使用CSLA框架的关键是理解DataPortal的概念。DataPortal框架对象负责管理所有数据访问活动。该对象定义一些特殊的方法,控制读写数据行为。你需要在业务对象中实现这些方法,来访问业务数据。DataPortal 会负责调用这些方法。 DataPortal 聪明地知道是否对象数据是脏的,是否需要保存。在业务对象的Save() 方法调用时,DataPortal 判断是否Save() 方法执行插入新数据的操作,或更新现存的数据。因为可在应用程序的 app.config 或 web.config 文件配置DataPortal,因此你可在不必重写应用程序代码的情况下,更改数据源的位置和网络协议。 源图片链接: 上图显示了CSLA框架中定义和实现的 DataPortal.Fetch<T>() 方法,和使用CSLA 框架对象实现的业务对象中 DataPortal_Fetch() 方法之间的关系。DataPortal_Fetch() 是其中一个特殊的方法,如想利用DataPortal 架构的强大功能,必须在业务对象代码中实现该方法。 使用DataPortal 检索对象数据的代码
public static BandsList GetBandsList(string countryCode)
{
//Create a Criteria object to pass retrieval information
//to the DataPortal
Critieria criteria = new Critieria();
//The countryCode parameter defines Bands that are
//associated with a given country as defined in the datasource.
criteria.CountryCode = countryCode; //Use the DataPortal mechanisms to make a
//BandsList collection
return DataPortal.Fetch(criteria);
} 在业务对象中实现DataPortal_Fetch() 方法 private void DataPortal_Fetch(Critieria criteria)
{
string countryCode = string.Empty;
if(criteria != null)
{
countryCode = criteria.CountryCode;
} using (SqlConnection cn =
new SqlConnection(MusicDataAccess.ConnectionString))
{
cn.Open();
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
if (!string.IsNullOrEmpty(countryCode))
{
cm.CommandText = “GetBandsByCountry”;
cm.Parameters.AddWithValue(“@CountryCode”,
criteria.CountryCode);
}
else
{
cm.CommandText = “GetBands”;
} using (SafeDataReader dr = new
SafeDataReader(cm.ExecuteReader()))
{
//Use the CSLA MarkAsChild method to make this
//list a child of the Catalog
MarkAsChild();
//Use the local programmer defined Fetch method, which is
//not part of the CSLA framework to load the individual band
//information into the list.
Fetch(dr);
}
}
}
} CSLA 框架的关键特性 CSLA 的设计目标是帮助你快速属性企业级应用程序的开发。为了实现这一目标,如下是一些期待的功能列表: - 源位置透明;
- 定制化认证;
- 内置角色授权;
- 内置业务规则验证;
- 强化的父子关系管理;
- N-level 撤销;
- 支持数据绑定;
- 全面支持事务;
源位置透明 – Source Location Transparency 使用工厂模式(factory pattern)的变种 class-in-charge 和DataPortal 框架,CSLA 可创建、检索数据和返回对象给调用方,而不要求调用方代码知道对象构造函数或数据。这样,可达到“任何地方,任何对象”功能,体现了CSLA框架 的价值。 不管对象来自于本地计算机、网络上的Application Server、或Web Service等等,你所获得的对象都是完全相同的。所有位置信息存放在应用程序的 app.config 或 web.config 配置文件中,可见的更改这些文件。 定制化认证和内置角色授权-Custom Authentication and Built-in Roles Authorization CSLA 提供的 Csla.ApplicationContext 对象作为一个通用的wrapper,同时支持 HttpContext 对象和 Application.Context 对象。此外,CSLA 框架允许开发人员设置用户角色授权信息,对象属性的读/写操作可赋予给每一个角色。 CSLA 业务对象支持定义和存储业务规则和验证数据输入。CSLA 业务对象基类 BusinessBase<T> 包含了一个 ValidationRules 集合,你可使用一系列预先定义的Validation 方法来添加业务规则。CSLA 提供了一个broken-rules 集合,你可遍历该集合来判断验证无效的原因。 重载 CSLA 对象的 AddBusinessRules() 方法
protected override void AddBusinessRules()
{
//Add a rule that says that the CountryCode property
//can not be greater in length than 4 characters.
ValidationRules.AddRule(
Csla.Validation.CommonRules.StringMaxLength,
new Csla.Validation.CommonRules.MaxLengthRuleArgs(“CountryCode”, 4));
} 当在检查CSLA 对象规则时,不符合条件的业务规则将添加到对象的 BrokenRulesCollection集合对象中。你可检测 BrokenRulesCollection 对象,并根据应用程序的对象进行处理。 调用ValidationRules.CheckRules() 方法,并处理BusinessRulesCollection集合
private void DataPortal_Create(Critieria criteria)
{
if (criteria != null)
{
_CountryCode = criteria.CountryCode;
} //Fire off rules checking
ValidationRules.CheckRules(); if(BrokenRulesCollection.Count >0)
{
StringBuilder sb = new StringBuilder(“Broken rules:”);
//Check the BrokenRulesCollection to see if there are
//any broken rules.
foreach (BrokenRule rule in BrokenRulesCollection)
{
sb.AppendLine(rule.Description);
}
throw new ArgumentException(sb.ToString());
}
} 强化的父子关系管理-Enhanced Parent-Child Relationship Management CSLA 强调了对分层数据的处理,允许你定义一个根对象(Root Object),并包含强类型和专属的集合对象。 CSLA 提供的父子关系管理,仅需要显式保存父对象,并智能保存所有的子对象。 CSLA 对父对象(根对象)和关联子对象集合的管理非常严格。在对象的创建时,CSLA提供了将对象标识为child-to-a-parent 对象的机制。一旦建立了关系,子对象仅在调用根对象(父对象)的Save() 方法时,才会保存。开发人员不必关注和检查子对象的状态 – CSLA 在后台负责监控。一旦 父对象的 Save() 方法调用,所有更新过的子对象和新增的对象将隐式保存。 N-Level 撤销 CSLA 支持N-Level 撤销。假定Musician 对象有一个属性 – Instruments,是Instrument 对象集合,表示特定的音乐家表演过的一个或多个 instruments。你可添加 guitar、vocals 和 trombone 值到对象集合中。 你可多次撤销操作,框架自动维护 Intruments 集合。为了实现 n-level 撤销,你需要做一些设置。一旦设置好,随后的实现将非常方便。 支持数据绑定和全面支持事务 – Support for Databinding and Full Support for Transactions CSLA 支持将 CSLA 对象绑定到 Web form 和 WinForm 控件上。你需要做的是配置标准的控件绑定属性,并调用控件的DataBind() 方法。 使用CSLA 对象作为数据感知控件的数据源,并进行标准数据绑定
//Get the instruments NameValueList
InstrumentsList list = InstrumentsList.GetList(); //Bind the NameValueList to the instruments
//DropDownList
ddInstruments.DataSource = list;
ddInstruments.DataTextField = “Value”;
ddInstruments.DataValueField = “Key”;
ddInstruments.DataBind(); CSLA 支持事务,只需要在数据方法上添加 [Transactional] 属性就可以调用事务支持,并在事务范围运行。
CSLA 框架的优点和缺点
在使用CSLA 开发企业应用程序时,需要考虑和评估该框架的一些优缺点。 优点:减轻企业应用开发的工作量
CSLA 减轻了企业应用开发过程中建立大型开发框架的工作量。一旦你选择CSLA框架,你不必考虑创建remoting 架构、实现支持数据绑定、或开发对象层级关系数据等等,CSLA 负责帮你实现这些功能。 优点:保持企业级应用开发的一致性
一旦CSLA 成为企业应用程序开发框架,开发团队的代码风格和设计实现基本会保持一致。如我们想了解其他开发人员如何实现数据检索操作,我们仅需查看业务对象的 DataPortal_Fetch() 方法。另外,集合对象的创建和层级对象数据的存储,都将保持一致风格。我们不必花费时间进行设计期讨论,CSLA 框架成为了设计标准。 优点:提供了对数据源和网络协议的灵活管理
我们知道CSLA 表示 Component-based Scalable Logical Architecture,Scalability 是CSLA 框架的第二个名称。数据源和网络协议支持在app.confg / web.config 文件中进行配置,可轻松实现对web service 的调用,转化为对 Enterprise Services 服务的调用。CSLA 框架帮助减少了对环境编程的工作量。 优点:提供了非常有用的工具类
CSLA 框架提供了一系列工具对象,让框架开发更加容易。下面代码演示了ObjectAdapter 类的使用,ObjectAdapter 将转换一个CSLA 强类型集合对象为数据源。
使用ObjectAdapter 类绑定集合对象到数据控件:
//Get the a musicians BusinessBaseList
MusiciansList musicians = MusiciansList.GetList(); //Use the ObjectAdapter to transform the list into
//a DataSet
ObjectAdapter adapter = new ObjectAdapter();
DataSet ds = new DataSet();
adapter.Fill(ds, musicians); //Bind the DataSet to the musician’s
//DropDownList
ddMusicians.DataSource = ds.Tables[0];
ddMusicians.DataTextField = “LastName”;
ddMusicians.DataValueField = “Id”;
ddMusicians.DataBind(); 此外,CSLA 提供了SmartDate 类,该类支持null 数据和文本数据。DataMapper 类允许映射属性和对象,或映射IDictionary 对象为CSLA 对象。SoartedBindList 类则支持对集合对象进行排序。最后,CSLA 还提供了SafeDataReader 类,可将null 数据转换为 空数据(empty data)或默认值。 缺点:需要时间学习
使用CSLA 框架并不是容易的事情,该框架需要较大的学习曲线和大量的时间学习。你需要逐步实践,尤其是充分利用DataPortal 功能。CSLA 适合于分布式环境大型项目,作者Lhotka编写的书(Expert C# 2008 Business Objects)是很好的学习资源,但该书包含大量细节,且每一个细节都涉及到应用程序的设计和CSLA 代码。刚开始可以跳过一些细节,然后在需要时,回头在看。一旦你掌握CSLA 开发技术之后,可以帮你节省大量的开发时间和软件功能测试时间。 缺点:需要OOP 专业知识
CSLA 大量使用了factory 设计模式、反射(reflection)、序列化、泛型、静态方法和抽象类(abstract class)等等,这些不是一个初学者掌握的。如果你计划使用CSLA,你需要考虑团队中至少有一位经验丰富的开发人员 – 可编写有效率的、有效的、高质量的面向对象代码,否则项目有编译错误的风险,且难以解决和理解运行行为。 缺点:需要深刻理解CSLA 框架
CSLA 是一个开发框架,不是一个开发方法 – 你需要学习,最好是按照框架约定的思路来使用框架。为了保持框架的灵活性和受益于框架的功能,尤其是 DataPortal 机制,最好是全面运用框架,否则在后期存在重构代码的风险。
CSLA 的确比较复杂,但并不是难以掌握。尽管框架提供了大量常规功能,但你仍然需要了解如何做其他工作,如调用 MarkNew() 方法改变对象状态;调用 MarkAsChind() 方法定义一个业务对象为父对象的子对象;还需要了解如何配置运行环境,让CSLA 客户端访问CSLA Application Server等等。这些是具体的操作,一旦你掌握如何执行之后,你可在企业应用开发中更加迅速。 缺点:使用反射,而不是接口方法实现
CSLA DataPortal 需要业务对象提供数据访问功能,实现一些特殊的方法(DataPortal_XYZ),以便DataPortal 在运行时调用。通常面向对象的技术中,确保指定业务对象的方法实现,可继承抽象类,或者让业务对象继承接口,这样,如果创建的业务对象没有实现需要的方法,将出现编译错误。
然而,DataPortal代码使用反射(reflection)来识别业务对象的特定数据存储和检索操作。毫无疑问,作者Lhotka 解释了这一情况,他认为使用反射可以不必在运行时间时检查这些特殊方法是否存在和实现。因此,你存在不小心部署了一些存在bug代码的风险。 原文链接:
Programming Within the CSLA
|