深度解析 BlogEngine.Net
最近买了本 C#2005 Business Objects 基于一个CSLA.NET开源项目展开的。大致看了下,觉得比较深奥。需要结合CSLA源码。不过在深入源码之前我决定先复习一个BlogEngine.Net。BlogEngine得核心类可以理解为是CSLA的阉割版。
BusinessBase 是BlogEngine所有业务的基类。
1.首先我们看下它继承了那些接口
public abstract class BusinessBase<TYPE, KEY> : IDataErrorInfo, INotifyPropertyChanged, IChangeTracking, IDisposable where TYPE : BusinessBase<TYPE, KEY>, new()
1.1 IDataErrorInfo
该功能提供用户界面可以绑定的自定义错误信息。
这个接口虽然被实现。我发现没有使用,不清楚作者如何处理了。
1.2 INotifyPropertyChanged
向客户端发出某一属性值已更改的通知。
/// <summary>
/// Occurs when this instance is marked dirty.
/// It means the instance has been changed but not saved.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
MSDN: ms-help://MS.MSDNQTR.v90.chs/fxref_system/html/d7424bfd-9de2-e553-d64e-57a78a2134d4.htm
INotifyPropertyChanged 接口用于向客户端(通常是执行绑定的客户端)发出某一属性值已更改的通知。
例如,考虑一个带有名为 FirstName 属性的 Person 对象。若要提供一般性属性更改通知,则 Person 类型实现 INotifyPropertyChanged 接口并在 FirstName 更改时引发 PropertyChanged 事件。如果数据源实现 INotifyPropertyChanged 并且您执行的是异步操作,则不得在后台线程上对数据源进行更改。相反,应在后台线程上读取这些数据并将这些数据合并到 UI 线程上的列表中。
若要在将客户端与数据源进行绑定时发出更改通知,则绑定类型应具有下列任一功能:
-
实现 INotifyPropertyChanged 接口(首选)。
-
为绑定类型的每个属性提供更改事件。
1.3 IChangeTracking
定义查询对象更改以及重置更改后的状态的机制。
1.4 IDisposable
这个大家都很熟悉了
1.5 where TYPE : BusinessBase<TYPE, KEY>, new()
所有业务类都必须继承这个BusinessBase,否则vs就会送你个error。
2.BusinessBase具有那些功能
2.1 获取对象的状态
2.1.1 IsNew
private bool _IsNew = true;
初始化=true
True: 说明这个对象是新创建的
False:说明已经存在这个对象了
2.1.2 IsDeleted,IsChanged
也是用来做判断标记
2.2 Validation 规则
IsValid 标记 是否需要验证。
ValidationRules()方法为虚方法。也是在继承类中实现,看下BlogRollItem.cs代码
AddRule()方法中最后一个参数确定了是否应用这些规则。
2
3 /// <summary>
4 /// Add or remove a broken rule.
5 /// </summary>
6 /// <param name="propertyName">The name of the property.</param>
7 /// <param name="errorMessage">The description of the error</param>
8 /// <param name="isBroken">True if the validation rule is broken.</param>
9 protected virtual void AddRule(string propertyName, string errorMessage, bool isBroken)
10 {
11 if (isBroken)
12 {
13 _BrokenRules[propertyName] = errorMessage;
14 }
15 else
16 {
17 if (_BrokenRules.ContainsKey(propertyName))
18 {
19 _BrokenRules.Remove(propertyName);
20 }
21 }
22 }
23
24 protected abstract void ValidationRules();
25
26 public bool IsValid
27 {
28 get
29 {
30 ValidationRules();
31 return this._BrokenRules.Count == 0;
32 }
33 }
BlogRollItem.cs
2 {
3 AddRule("Title", "Title must be set", string.IsNullOrEmpty(Title));
4 AddRule("BlogUrl", "BlogUrl must be set", BlogUrl == null);
5 }
最后在提交按钮之前做了处理 ,代码截取了片段
ValidationMessage 是将错误信息写成字符串的一个方法
BusinessBase .cs
2 {
3
4 if (IsDeleted && !(IsAuthenticated || isValidated))
5 throw new System.Security.SecurityException("You are not authorized to delete the object");
6
7 if (!IsValid && !IsDeleted)
8 throw new InvalidOperationException(ValidationMessage);
9
10 return SaveAction.None;
11 }
2.3 通用数据访问
运用了模板模式,在其继承类实现DataSelect方法。调用其继承类的A类的方法只需XXX.Load(id).
而无需在A类设定对象的状态,体现了代码的高度重用。
代码如下:
1 /// <summary>
2 /// Loads an instance of the object based on the Id.
3 /// </summary>
4 /// <param name="id">The unique identifier of the object</param>
5 public static TYPE Load(KEY id)
6 {
7 TYPE instance = new TYPE();
8 instance = instance.DataSelect(id);
9 instance.Id = id;
10
11 if (instance != null)
12 {
13 instance.MarkOld();
14 return instance;
15 }
16
17 return null;
18 }
19
20 /// <summary>
21 /// Retrieves the object from the data store and populates it.
22 /// </summary>
23 /// <param name="id">The unique identifier of the object.</param>
24 /// <returns>True if the object exists and is being populated successfully</returns>
25 protected abstract TYPE DataSelect(KEY id);
再看一个方法:
2 /// Saves the object to the data store (inserts, updates or deletes).
3 /// </summary>
4 public virtual SaveAction Save(string userName, string password)
5 {
6 bool isValidated;
7 if (userName == string.Empty)
8 isValidated = false;
9 else
10 isValidated = Membership.ValidateUser(userName, password);
11
12 if (IsDeleted && !(IsAuthenticated || isValidated))
13 throw new System.Security.SecurityException("You are not authorized to delete the object");
14
15 if (!IsValid && !IsDeleted)
16 throw new InvalidOperationException(ValidationMessage);
17
18 if (IsDisposed && !IsDeleted)
19 throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "You cannot save a disposed {0}", this.GetType().Name));
20
21 if (IsChanged)
22 {
23 return Update();
24 }
25
26 return SaveAction.None;
27 }
也是运用了模板模式,和上一段代码的区别在于使用了虚方法。
总结:BlogEngine.Net是个非常好的学习源码。