.NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略

转载 2012年03月16日 08:37:43
 前言:之前的讨论一直关注在怎么从DAL中获取数据,以及数据的Mapping问题。实际上,一个业务框架最主要的作用就是简化业务逻辑的编写和开发。

 

  本篇的议题如下:

    1. 框架的借鉴
    2. 综合考虑

1. 框架的借鉴

  一个框架的产生不是那么简单的,有很多的问题需要Richard去考虑:

    1. 避免重新造轮子
    2. 借鉴现有的成熟的框架的思想

 

在开发的过程中,Richard一直使用Visual Studio IDE开发。而且每次随着VS新版本的发布,总是伴随着新技术的产生。很多的时候,开发人员只是关注在新技术的使用和学习上。但是对于新技术,还有另外一方面是很值得关注的:实现的原理,和为什么这样实现,即,思想。新技术,毫无疑问是一些大师们思考的结果,从他们的思想中借鉴,益处是很大的。

 

Richard学习的过程中,有一个地方特别引起来他的关注:那就是依赖属性概念的提出,先是WPF,然后在他学习WF的时候,也看到了依赖属性的再次使用。他考虑,把依赖属性的思想使用到自己正在开发的业务框架中来。

 

首先,他分析了现在的依赖属性的实现方式(以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一直认为,一个属性的声明是很简单的,而且长期以来Richard都一直使用下面的方式:

 

public Thickness Margin
{

       
get;set;

}

 

  比较而言,依赖属性最大的好处就于:给普通的属性提供更加多的信息,而且提供了更多的功能:验证,触发回调事件。当然,使用普通的属性也能达到:

  

public Thickness Margin
{

       
get{return margin;}
       
set
       {

              
if(margin<0)
                     ...
              ...
       }
}
 

相比而言,依赖的属性的方式更加优雅,而且扩展性也好。

 

还有一点比较重要的就是,一旦把一个属性变为依赖属性,那么.NET Framework就开始管理这个属性,如自动的验证,值的改变和跟踪。这样就把任务交给了Framework,开发人员做事情就比较方便了。

 

Richard想起了之前在开发业务类中遇到的问题:例如下面的代码:

 

public class Product
{

        
public string ProductName{get;set;}

        
public double Price{get;set;}

}

 

很多的时候,在增加或者更新一个Product的时候,由于逻辑的需要,往往要判断ProductName不为空,而且Price要大于零等。所以每次都需要写代码判断:

   

        public void Add()
        {

              
if(string.IsNullOrEmpty(this.ProductName){...}

              
if(this.Price<0){...}

        }

 

  问题还不止这些,如果在其他的业务类中也需要同样,而且类似的验证,那只有一行行的写类似的代码,最好的情况就是copy一些代码。

 

       这样写代码确实很累,后面Richard也想用一些方式来改进,用到了Enterprise Library中的Validation验证模块,于是代码就变成了下面的样子:

 

 

public class Product
{

        [NotNullValidator]

        
public string ProductName{get;set;} 

        
public double Price{get;set;}    

}
 

使用声明的开发,AOP的思想,其实这样的方式相比之前而言,确实已经很不错了。在把业务类的数据保存的时候只要调用Validation验证模块的Validate()方法就行了。确实很方便,但是存在的问题就是:每次调用Validate()方法时候,就会把这个业务类的所有属性都会检查一遍(那些加了验证标签的属性),这样,性能方面不好,而且还不能针对某一个属性单独的验证。

 

  2. 综合考虑

Richard还考虑到了另外的一点:之前一直在解决mapping的问题,说到底就是把从DAL中拿到的数据赋值给业务类的属性。而且还要基于业务类创建查询对象,最后把查询对象解析为SQL语句,所以还要保存业务属性和DAL中数据实体属性的对应关系,即哪个业务属性对应哪个数据实体属性(也是表字段)。

 

综合上面的考虑,Richard决定把依赖属性的优势利用起来(自动的验证,数据改变跟踪,另外加上权限的验证),而且给依赖属性更多的元数据信息:把mapping的字段信息保存在依赖属性中。所以,现在属性的声明如下:

 

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); }
    }

 

 

在上面的属性声明中,就指定从业务类(如,Product)的属性从哪个数据实体(typeof(m_Product))的哪个属性(如,Id)取值。

RegisterProperty就是把属性的信息保存在一个字典中:

Dictionary<Type,List< IPropertyInfo>>

其中PropertyInfo继承了IPropertyInfo接口。

最后的结果就是:所有业务类的mapping属性都被保存在了一个全局的静态字典中。

 

另外还有一个全局的静态字典用来保存每个属性所对应的验证规则:

Dictionary< IPropertyInfo,List<ICheckRule>>

所有的验证规则都是从ICheckRule接口继承。

 

一个比较强大的属性就产生了。当然,在mapping属性中的验证只是基本的验证,还有更加复杂的业务验证将会放在其他的地方,实现方式或者类似WPF那么:采用回调,如new ValidateValueCallback(FrameworkElement.IsMarginValid)。

 

所以,借鉴于mapping属性就解决了三个问题:

    1. mapping和查询对象的实现
    2. 部分验证规则的声明
    3. 业务属性的管理

    版权为小洋和博客园所有,欢迎转载,转载请标明出处给作者。

     http://www.cnblogs.com/yanyangtian

 

.NET 业务框架开发实战

.NET 分布式架构开发实战之一 故事起源     前言:本系列文章主要讲述一个实实在在的项目开发的过程,主要包含:提出问题,解决问题,架构设计和各个逻辑层的实现以及新问题的出现和代码的重构。本系...
  • E_eric
  • E_eric
  • 2013年06月04日 22:26
  • 660

.NET 业务框架开发实战之八 业务层Mapping的选择策略

前言:在上一篇文章中提到了mapping,感觉很像在重新实现NHibernate。其实文章的本意是想反映出Richard在思考的时候的一些选择:利用现有的,还是最后自己用别的方式实现。如果一上来就说什...
  • huanghunjiuba
  • huanghunjiuba
  • 2012年03月16日 08:36
  • 306

.NET框架基本原理

1.1  将源代码编译为托管模块    在.NET框架里,正如前言里说的“编译器编译面向.NET框架的源代码产生CIL,只有到了运行时,CLR才将CIL翻译为CPU指令”。1、程序员先用任何支持CLR...
  • doong
  • doong
  • 2006年02月16日 16:40
  • 1623

spring学习日志之四 IOC原理

1,Spring的IOC IOC(控制反转:Inverseof Control)是Spring容器的核心,AOP、声明式事务等功能都是以IOC作为基础展开的。控制反转的含义是:调用类对某一接口实现类...
  • xuqiaobo
  • xuqiaobo
  • 2016年08月16日 17:55
  • 298

(Shadow Mapping) 阴影映射原理与实现

阴影贴图(Shadow mapping)是在三维计算机图形中加入阴影的过程。阴影贴图的概念最初是由 Lance Williams 于 1978年在“在曲面上投射阴影”这篇论文中提出的。从那时开始,这...
  • xiaoge132
  • xiaoge132
  • 2016年05月20日 07:51
  • 2992

.net framework 工作原理

   通过学习,对,net framework的工作机理有所了解,现在总结如下:                                                 编码语言(c#,vb....
  • JustLovePro
  • JustLovePro
  • 2007年05月08日 21:41
  • 2508

拓扑关系——九交模型

空间关系 中文名称 OGC标准 解释 Contains 包含 是 一个几何图形的内部完全包含了另一个几何图形的内部和边界。 CoveredBy 覆盖 否...
  • qq_28934471
  • qq_28934471
  • 2015年06月11日 08:42
  • 3368

.NET 业务框架开发实战之六 DAL的重构

前言:其实这个系列还是之前的".NET 分布式架构开发实战 ",之所以改了名字,主要是因为文章的标题带来了不少的歧义:系列文章中本打算开发一个简化业务发的流程的Framework,然后用这个Frame...
  • huanghunjiuba
  • huanghunjiuba
  • 2012年03月15日 16:49
  • 366

Quartz.NET 任务调度框架 - 01

在之前的博客中,介绍过Quartz任务调度框架(Java版本)。最近在.NET平台使用了Quartz任务调度框架,并且结合TopShelf框架,把Quartz发布成Windows Service。 今...
  • afandaafandaafanda
  • afandaafandaafanda
  • 2015年08月06日 22:12
  • 1541

小评几种O/R Mapping工具

LLBLGen Pro  满意度: 撞头度:        作为一个商业组件,可以说它是一个令我不知所措的一个工具,它提供的功能超出了我的想象,犹其在易用性上,提供了一个非常漂亮的界面,可以很自由的制...
  • zhiyang202
  • zhiyang202
  • 2005年07月19日 10:43
  • 1029
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:.NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略
举报原因:
原因补充:

(最多只允许输入30个字)