[原创].NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略
.NET 業(yè)務(wù)框架開發(fā)實(shí)戰(zhàn)之九 Mapping屬性原理和驗(yàn)證規(guī)則的實(shí)現(xiàn)策略
前言:之前的討論一直關(guān)注在怎么從DAL中獲取數(shù)據(jù),以及數(shù)據(jù)的Mapping問題。實(shí)際上,一個(gè)業(yè)務(wù)框架最主要的作用就是簡化業(yè)務(wù)邏輯的編寫和開發(fā)。
?
本篇的議題如下:
?
系列文章鏈接:
?[原創(chuàng)].NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之一 故事起源
[原創(chuàng)].NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之二 草稿設(shè)計(jì)
[原創(chuàng)].NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之三 數(shù)據(jù)訪問深入一點(diǎn)的思考
[原創(chuàng)].NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之四 構(gòu)建從理想和實(shí)現(xiàn)之間的橋梁(前篇)
[原創(chuàng)].NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)五 Framework改進(jìn)篇
[原創(chuàng)].NET 業(yè)務(wù)框架開發(fā)實(shí)戰(zhàn)之六 DAL的重構(gòu)
[原創(chuàng)].NET 業(yè)務(wù)框架開發(fā)實(shí)戰(zhàn)之七 業(yè)務(wù)層初步構(gòu)想
[原創(chuàng)].NET 業(yè)務(wù)框架開發(fā)實(shí)戰(zhàn)之八 業(yè)務(wù)層Mapping的選擇策略
[原創(chuàng)].NET 業(yè)務(wù)框架開發(fā)實(shí)戰(zhàn)之九 Mapping屬性原理和驗(yàn)證規(guī)則的實(shí)現(xiàn)策略
[原創(chuàng)].NET 業(yè)務(wù)框架開發(fā)實(shí)戰(zhàn)之十 第一階段總結(jié),深入淺出,水到渠成(前篇)
[原創(chuàng)].NET 業(yè)務(wù)框架開發(fā)實(shí)戰(zhàn)之十 第一階段總結(jié),深入淺出,水到渠成(后篇)
1.?框架的借鑒
一個(gè)框架的產(chǎn)生不是那么簡單的,有很多的問題需要Richard去考慮:
?
在開發(fā)的過程中,Richard一直使用Visual Studio IDE開發(fā)。而且每次隨著VS新版本的發(fā)布,總是伴隨著新技術(shù)的產(chǎn)生。很多的時(shí)候,開發(fā)人員只是關(guān)注在新技術(shù)的使用和學(xué)習(xí)上。但是對(duì)于新技術(shù),還有另外一方面是很值得關(guān)注的:實(shí)現(xiàn)的原理,和為什么這樣實(shí)現(xiàn),即,思想。新技術(shù),毫無疑問是一些大師們思考的結(jié)果,從他們的思想中借鑒,益處是很大的。
?
在Richard學(xué)習(xí)的過程中,有一個(gè)地方特別引起來他的關(guān)注:那就是依賴屬性概念的提出,先是WPF,然后在他學(xué)習(xí)WF的時(shí)候,也看到了依賴屬性的再次使用。他考慮,把依賴屬性的思想使用到自己正在開發(fā)的業(yè)務(wù)框架中來。
?
首先,他分析了現(xiàn)在的依賴屬性的實(shí)現(xiàn)方式(以WPF為例),
?
代碼 public?class?FrameworkElement:?UIElement,?...{
???????public?static?readonly?DependencyProperty?MarginProperty;
???????...
}
?
public?Thickness?Margin
{
???????set?{?SetValue(MarginProperty,?value);?}
???????get?{?return?(Thickness)GetValue(MarginProperty);?}
}
?
static?FrameworkElement()
{
???????FrameworkPropertyMetadata?metadata?=?new?FrameworkPropertyMetadata(
??????????????new?Thickness(),?FrameworkPropertyMetadataOptions.AffectsMeasure);
???????MarginProperty?=?DependencyProperty.Register("Margin",
??????????????typeof(Thickness),?typeof(FrameworkElement),?metadata,
??????????????new?ValidateValueCallback(FrameworkElement.IsMarginValid));???...
}
?
?
在Richard一直認(rèn)為,一個(gè)屬性的聲明是很簡單的,而且長期以來Richard都一直使用下面的方式:
?
public?Thickness?Margin{
???????get;set;
}
?
?
比較而言,依賴屬性最大的好處就于:給普通的屬性提供更加多的信息,而且提供了更多的功能:驗(yàn)證,觸發(fā)回調(diào)事件。當(dāng)然,使用普通的屬性也能達(dá)到:
public?Thickness?Margin
{
???????get{return?margin;}
???????set
???????{
??????????????if(margin<0)
?????????????????????...
??????????????...
???????}
}
?
?
相比而言,依賴的屬性的方式更加優(yōu)雅,而且擴(kuò)展性也好。
?
還有一點(diǎn)比較重要的就是,一旦把一個(gè)屬性變?yōu)橐蕾噷傩?#xff0c;那么.NET Framework就開始管理這個(gè)屬性,如自動(dòng)的驗(yàn)證,值的改變和跟蹤。這樣就把任務(wù)交給了Framework,開發(fā)人員做事情就比較方便了。
?
Richard想起了之前在開發(fā)業(yè)務(wù)類中遇到的問題:例如下面的代碼:
?
public?class?Product{
????????public?string?ProductName{get;set;}
????????public?double?Price{get;set;}
}
?
?
很多的時(shí)候,在增加或者更新一個(gè)Product的時(shí)候,由于邏輯的需要,往往要判斷ProductName不為空,而且Price要大于零等。所以每次都需要寫代碼判斷:
???
????????public?void?Add()????????{
??????????????if(string.IsNullOrEmpty(this.ProductName){...}
??????????????if(this.Price<0){...}
????????}
?
?
問題還不止這些,如果在其他的業(yè)務(wù)類中也需要同樣,而且類似的驗(yàn)證,那只有一行行的寫類似的代碼,最好的情況就是copy一些代碼。
?
?????? 這樣寫代碼確實(shí)很累,后面Richard也想用一些方式來改進(jìn),用到了Enterprise Library中的Validation驗(yàn)證模塊,于是代碼就變成了下面的樣子:
?
?
public?class?Product{
????????[NotNullValidator]
????????public?string?ProductName{get;set;}?
????????public?double?Price{get;set;}????
}
?
?
使用聲明的開發(fā),AOP的思想,其實(shí)這樣的方式相比之前而言,確實(shí)已經(jīng)很不錯(cuò)了。在把業(yè)務(wù)類的數(shù)據(jù)保存的時(shí)候只要調(diào)用Validation驗(yàn)證模塊的Validate()方法就行了。確實(shí)很方便,但是存在的問題就是:每次調(diào)用Validate()方法時(shí)候,就會(huì)把這個(gè)業(yè)務(wù)類的所有屬性都會(huì)檢查一遍(那些加了驗(yàn)證標(biāo)簽的屬性),這樣,性能方面不好,而且還不能針對(duì)某一個(gè)屬性單獨(dú)的驗(yàn)證。
?
2.?綜合考慮
Richard還考慮到了另外的一點(diǎn):之前一直在解決mapping的問題,說到底就是把從DAL中拿到的數(shù)據(jù)賦值給業(yè)務(wù)類的屬性。而且還要基于業(yè)務(wù)類創(chuàng)建查詢對(duì)象,最后把查詢對(duì)象解析為SQL語句,所以還要保存業(yè)務(wù)屬性和DAL中數(shù)據(jù)實(shí)體屬性的對(duì)應(yīng)關(guān)系,即哪個(gè)業(yè)務(wù)屬性對(duì)應(yīng)哪個(gè)數(shù)據(jù)實(shí)體屬性(也是表字段)。
?
綜合上面的考慮,Richard決定把依賴屬性的優(yōu)勢(shì)利用起來(自動(dòng)的驗(yàn)證,數(shù)據(jù)改變跟蹤,另外加上權(quán)限的驗(yàn)證),而且給依賴屬性更多的元數(shù)據(jù)信息:把mapping的字段信息保存在依賴屬性中。所以,現(xiàn)在屬性的聲明如下:
?
代碼 public?static?readonly?PropertyInfo<int>?ProductIdProperty?=?RegisterProperty<Product>(????????????new?PropertyInfo<int>("ProductId",typeof(M_Product)","Id"));?
????public?string?ProductId
????{
??????get?{?return?ReadProperty(ProductIdProperty);?}
??????set?{?LoadProperty(ProductIdProperty,?value);?}
????}
?
?
在上面的屬性聲明中,就指定從業(yè)務(wù)類(如,Product)的屬性從哪個(gè)數(shù)據(jù)實(shí)體(typeof(m_Product))的哪個(gè)屬性(如,Id)取值。
RegisterProperty就是把屬性的信息保存在一個(gè)字典中:
Dictionary<Type,List< IPropertyInfo>>
其中PropertyInfo繼承了IPropertyInfo接口。
最后的結(jié)果就是:所有業(yè)務(wù)類的mapping屬性都被保存在了一個(gè)全局的靜態(tài)字典中。
?
另外還有一個(gè)全局的靜態(tài)字典用來保存每個(gè)屬性所對(duì)應(yīng)的驗(yàn)證規(guī)則:
Dictionary< IPropertyInfo,List<ICheckRule>>
所有的驗(yàn)證規(guī)則都是從ICheckRule接口繼承。
?
一個(gè)比較強(qiáng)大的屬性就產(chǎn)生了。當(dāng)然,在mapping屬性中的驗(yàn)證只是基本的驗(yàn)證,還有更加復(fù)雜的業(yè)務(wù)驗(yàn)證將會(huì)放在其他的地方,實(shí)現(xiàn)方式或者類似WPF那么:采用回調(diào),如new ValidateValueCallback(FrameworkElement.IsMarginValid)。
?
所以,借鑒于mapping屬性就解決了三個(gè)問題:
? 版權(quán)為小洋和博客園所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)標(biāo)明出處給作者。
?? http://www.cnblogs.com/yanyangtian
?
下篇講述:.NET 業(yè)務(wù)框架開發(fā)實(shí)戰(zhàn)之十 水到渠成,發(fā)布框架實(shí)現(xiàn)的第一個(gè)版本
?
轉(zhuǎn)載于:https://www.cnblogs.com/yanyangtian/archive/2010/06/17/1759327.html
總結(jié)
以上是生活随笔為你收集整理的[原创].NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c# GDI+画折线图(初级版本)
- 下一篇: OpenGL绘图过程简述