和我一起學(xué)CSLA.NET----創(chuàng)建業(yè)務(wù)對象3
到現(xiàn)在為止, 我們已經(jīng)為業(yè)務(wù)對象創(chuàng)建了屬性,驗證規(guī)則,數(shù)據(jù)門戶.除了屬性我們會直接使用,驗證規(guī)則和數(shù)據(jù)門戶我們不會手動直接調(diào)用的,而最通常調(diào)用的是我們的業(yè)務(wù)對象的工廠方法,在這一節(jié),我們就為Product對象添加了些通用的工廠業(yè)務(wù)方法,并且介紹一下工廠方法調(diào)用的內(nèi)部細節(jié),以及業(yè)務(wù)對象的相關(guān)細節(jié)。
首先我們必須要了解一下業(yè)務(wù)對象的Save方法,這個方法是CSLA約定的基本業(yè)務(wù)對象BusinessBase<T>內(nèi)置實現(xiàn)的,源代碼如下:
-
public virtual T Save() -
{ -
T result;
-
if (this.IsChild)
-
throw new NotSupportedException(Resources.NoSaveChildException);
-
if (EditLevel > 0) -
throw new Validation.ValidationException(Resources.NoSaveEditingException); -
if (!IsValid && !IsDeleted) -
throw new Validation.ValidationException(Resources.NoSaveInvalidException); -
if (IsBusy) -
throw new Validation.ValidationException(Resources.BusyObjectsMayNotBeSaved); -
if (IsDirty) -
result = (T)DataPortal.Update(this); -
else -
result = (T)this; -
OnSaved(result, null, null);
-
return result; -
}
前幾個判斷和異常我們暫且不管,我們看到當(dāng)屬性IsDirty為True時,會調(diào)用數(shù)據(jù)門戶的Update(以下是此方法代碼片斷),而在Update方法內(nèi)部,CSLA其實是會根據(jù)當(dāng)前業(yè)務(wù)對象不同的狀態(tài)進行不同的處理,如果業(yè)務(wù)對象是新增對象(IsNew=True),則通過反射調(diào)用業(yè)務(wù)對象的DataPortal_Insert方法,如果為已經(jīng)標記刪除的對象(IsDeleted=True),則調(diào)用對象的DataPortal_DeleteSelf方法,否則調(diào)用業(yè)務(wù)對象的更新方法DataPortal_Update, 以下就是DataPortal.Update方法的內(nèi)部代碼片斷:
-
string methodName; -
if (obj is CommandBase)
-
{ -
//注意這里的方法名都是寫死的,這和基類BusinessBase里定義的一致,所以數(shù)據(jù)門戶的方法名是固定的 -
methodName = "DataPortal_Execute"; -
operation = DataPortalOperations.Execute;
-
//反射之前會進行權(quán)限判斷 -
if (!Csla.Security.AuthorizationRules.CanEditObject(objectType)) -
throw new System.Security.SecurityException(string.Format(Resources.UserNotAuthorizedException,
-
"execute", -
objectType.Name));
-
}
-
else -
{ -
var bbase = obj as Core.BusinessBase; -
if (bbase != null)
-
{ -
if (bbase.IsDeleted) -
{ -
methodName = "DataPortal_DeleteSelf"; -
if (!Csla.Security.AuthorizationRules.CanDeleteObject(objectType)) -
throw new System.Security.SecurityException(string.Format(Resources.UserNotAuthorizedException,
-
"delete", -
objectType.Name));
-
}
-
else -
if (bbase.IsNew) -
{ -
methodName = "DataPortal_Insert"; -
if (!Csla.Security.AuthorizationRules.CanCreateObject(objectType)) -
throw new System.Security.SecurityException(string.Format(Resources.UserNotAuthorizedException,
-
"create", -
objectType.Name));
-
}
-
else -
{ -
methodName = "DataPortal_Update"; -
if (!Csla.Security.AuthorizationRules.CanEditObject(objectType)) -
throw new System.Security.SecurityException(string.Format(Resources.UserNotAuthorizedException,
-
"save", -
objectType.Name));
-
}
-
}
-
else -
{ -
methodName = "DataPortal_Update"; -
if (!Csla.Security.AuthorizationRules.CanEditObject(objectType)) -
throw new System.Security.SecurityException(string.Format(Resources.UserNotAuthorizedException,
-
"save", -
objectType.Name));
-
}
-
}
-
method = Server.DataPortalMethodCache.GetMethodInfo(obj.GetType(), methodName);
-
}
-
//...下面是調(diào)用這個方法了
這里列出來了比較多的代碼,其實這也是一種學(xué)習(xí)CSLA框架的一個手段,他的源代碼并不是很復(fù)雜,結(jié)合著實例去學(xué)習(xí)他的源代碼對我們能夠很好的使用這個開源框架很有幫助. 很多問題只有你知道了它的具體原理,你才能夠真正的去充分利用它的價值,也就會避免來濫用它.不要迷戀它,也不能低估它.
以上之所以介紹業(yè)務(wù)對象的Save方法,是想說明,在這個方法內(nèi)部已經(jīng)提供了業(yè)務(wù)對象的更新,延遲刪除,保存,所以說我們工廠方法沒有必要提供這三個方法了,這樣我們暫時不考慮業(yè)務(wù)直接相關(guān)的方法,還差創(chuàng)建對象,直接刪除,獲取對象三個方法了,我們依次添加這三個方法:
-
#region Factory Methods -
public static Product NewProduct()
-
{ -
return DataPortal.Create<Product>();
-
}
-
public static Product GetProduct(string id)
-
{ -
return DataPortal.Fetch<Product>(new SingleCriteria<Product, string>(id));
-
}
-
public static void DeleteProduct(string id)
-
{ -
DataPortal.Delete(new SingleCriteria<Product, string>(id));
-
}
-
private Product() -
{ } -
#endregion
1.首先是創(chuàng)建對象的方法NewProduct(),可能有些人可能會不太明白這個方法為什么存在,CSLA約定所有業(yè)務(wù)對象實現(xiàn)非public構(gòu)造函數(shù),防止用戶new一個業(yè)務(wù)對象,強制UI開發(fā)人員使用工廠方法來使用業(yè)務(wù)對象,可以看到我們最下面的默認構(gòu)造方法都是私有的,你不能夠在外面直接通過new來創(chuàng)建我們的業(yè)務(wù)對象.
2.業(yè)務(wù)方法調(diào)用的數(shù)據(jù)門戶相應(yīng)的實現(xiàn),其實就和業(yè)務(wù)對象的數(shù)據(jù)門戶的方法一一對應(yīng),這個我們在上一節(jié)有介紹,比如這里調(diào)用的DataProtal.Create其實就是調(diào)用的我們的業(yè)務(wù)對象內(nèi)部實現(xiàn)的DataPortal_Create,只不在調(diào)用時自動封裝了上下文,進行了通道處理,進行了安全驗證.
3.業(yè)務(wù)方法都是static的靜態(tài)方法.
到現(xiàn)在為止,我們已經(jīng)完成了一個基本的業(yè)務(wù)對象,包括它的屬性,驗證,數(shù)據(jù)門戶,業(yè)務(wù)方法,現(xiàn)在可以對我們的業(yè)務(wù)對象進行一下測試了,很簡單,我們使用Vs.Net帶的單元測試,新建一個測試項目, 然后注意新增一個配置文件來配置我們的數(shù)據(jù)庫連接, 再添加我們針對Product業(yè)務(wù)對象的單元測試類即可了,我們先簡單的測試一下創(chuàng)建和保存方法:
-
/// <summary> -
///NewProduct 的測試
-
///</summary> -
[TestMethod()] -
public void NewProductTest() -
{ -
Product actual; -
actual = Product.NewProduct(); -
actual.ItemNo = "000001"; -
actual.ItemName = "山寨手機Nexus one"; -
Assert.IsNotNull(actual.ProductID); -
}
-
[TestMethod()] -
public void SaveProductTest() -
{ -
Product actual; -
actual = Product.NewProduct(); -
actual.ItemNo = "000001"; -
actual.ItemName = "山寨手機Nexus one"; -
actual.Save();
-
Product expected = Product.GetProduct(actual.ProductID);
-
Assert.IsNotNull(expected); -
Assert.AreEqual(actual.ItemNo, expected.ItemNo); -
}
右擊運行單元測試,我們可以直接查看測試結(jié)果,直接測試我們的業(yè)務(wù)對象的相關(guān)特性,或者是調(diào)試過程來查看一些內(nèi)部流程.
接下來,還是來提示一些業(yè)務(wù)對象的一些使用上的細節(jié):
1.當(dāng)使用工廠方法NewXXX創(chuàng)建一個對象后,在DataPortal_Create里對這個對象的默認值進行初始化,對象的屬性IsNew=True,然后需要調(diào)用業(yè)務(wù)對象內(nèi)置的Save方法,才保存這個對象
2.如果你調(diào)用業(yè)務(wù)對象內(nèi)置的Delete()方法,其實是設(shè)置這個業(yè)務(wù)對象的IsDeleted=True,IsDirty=True,然后需要調(diào)用業(yè)務(wù)對象內(nèi)置的Save方法,來完成這個對象的持久化,這就是我們提到過的延遲刪除(也可以通過查看我們上面提到的Save方法的內(nèi)部處理看出來).
3.如果你調(diào)用業(yè)務(wù)對象內(nèi)置的Save方法,對象不是是以上說的兩種情況,而且進行過更改,屬于臟對象(IsDirty=True),那么會執(zhí)行這個對象的更新操作,也就是會調(diào)用數(shù)據(jù)門戶提供的DataPortal_Update方法.
不過我們的業(yè)務(wù)對象還比較簡單,到現(xiàn)在并沒有考慮到主子關(guān)系,也沒有處理安全驗證,更沒有應(yīng)用CSLA的移動對象,這些概念我們會在下面一一介紹.
作者:孤獨俠客(似水流年)
出處:http://lonely7345.cnblogs.com/
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。

浙公網(wǎng)安備 33010602011771號