和我一起学CSLA.NET----创建业务对象1

     我们已经准备好了环境,下面我们就来介绍CSLA业务对象的创建,如果你还没有下载CSLA,请在这里下载CSLA.NET,我们使用的是3.8.2版本(本来想使用4.0版本,后来发现是针对framework 4.0的)。
     建立类库项目CSLADemo.Library,引用下载的Csla.dll和System.Windows.Interactivity.dll(CSLA依赖),另外还需要引用我们的linq项目。在这一节我们先介绍CSLA业务对象一些基础的东西的实现,在这里包括业务属性,基本业务方法,基本数据验证,以及基本的数据门户.
   在这之前,先介绍一下CSLA的其中的几个主要的业务基类:
     Csla.BusinessBase         所有可编辑的业务类都要继承的基类
     Csla.BusinessListBase    所有可编辑的业务集合类都要继承的基类
     Csla.ReadOnlyBase        所有只读的业务类都要继承的基类
     Csla.ReadOnlyListBase   所有只读的业务集合类都要继承的基类

    使用之前版本的CSLA时,都是直接继承这几个基类,现在的版本已经利用泛型对这些基类进行了封装。我们以产品(Product)业务类为例来新建一个业务类,在这里有个建议,如果你的项目比较大,而且多人维护,或者是由代码生成,你可以考虑用partial类,这样可以将生成的代码与自定义的代码分开,或者是分成业务方法,工厂方法,数据门户等几个不同的分布类文件,这样也会方便源代码管控。
     我们添加Product的三个属性:  

隐藏行号 复制代码 Product
  1. 
    
  2. [Serializable()]
    
  3. public class Product : BusinessBase<Product>
    
  4. {
    
  5.     #region  Business Methods
    
  6. 
    
  7.     private static PropertyInfo<string> ProductIDProperty =
    
  8.       RegisterProperty<string>(p => p.ProductID, "产品编号");
    
  9.     public string ProductID
    
  10.     {
    
  11.         get { return GetProperty(ProductIDProperty); }
    
  12.         set { SetProperty(ProductIDProperty, value); }
    
  13.     }
    
  14. 
    
  15.     private static PropertyInfo<string> ItemNoProperty =
    
  16.     RegisterProperty<string>(p => p.ItemNo, "产品编号");
    
  17.     public string ItemNo
    
  18.     {
    
  19.         get { return GetProperty(ItemNoProperty); }
    
  20.         set { SetProperty(ItemNoProperty, value); }
    
  21.     }
    
  22. 
    
  23. 
    
  24.     private static PropertyInfo<string> ItemNameProperty =
    
  25.     RegisterProperty<string>(p => p.ItemName, "产品名称");
    
  26.     public string ItemName
    
  27.     {
    
  28.         get { return GetProperty(ItemNameProperty); }
    
  29.         set { SetProperty(ItemNameProperty, value); }
    
  30.     }
    
  31. 
    
  32. 
    
  33.     public override string ToString()
    
  34.     {
    
  35.         return ProductID.ToString();
    
  36.     }
    
  37. 
    
  38.     #endregion
    
  39. }
    

 

   这可和我们的通常使用的简单实体的属性差别很大,甚至和之前版本都不一样,有几点需要注意:
       1.类必须打上Serializable标签,因为整个对象是需要序列化传输的。
       2.因为Product是单个可编辑的业务基类,所以直接继承BusinessBase<T>
       3.同时使用了私有变量和属性,而且私有变量必须是static,这样能够保证在对象调用之前已经注册PropertyInfo,当然你可以在构造函数里面调用RegisterProperty,不过不推荐这样。主要原因是如果是非静态变量注册PropertyInfo,你的默认序列化时也会报错,另外使用静态变量可以节约内存,因为对于不同的实例来说,这些注册的属性信息也都是一样的。
详细讨论
       4.之前版本是通过属性上打标签的方法,通过反射来获取属性信息,而现在是通过直接PropertyInfo,通过FieldDataManager/PropertyInfoManager来管理,其中还将PropertyInfo列表缓存,主要是为了提供性能。
       5.可以提供PropertyInfo类型的信息包括属性类型,属性友好名称,默认值,关系类型等,而这些信息都会被CSLA直接使用(见下代码).
       6.每个属性的set,get都通过基类的GetProperty,SetProperty来实现,在读取和设置的过程中,其实是进行了权限的判断,判断对当前属性是否有相应的读或者写的权限.我们来看下GetProperty的部分源代码:

隐藏行号 复制代码 BusinessBase.GetProperty
  1. protected P GetProperty<P>(PropertyInfo<P> propertyInfo, Security.NoAccessBehavior noAccess)
    
  2.   {
    
  3.     P result = default(P);
    
  4.     if (_bypassPropertyChecks || CanReadProperty(propertyInfo.Name, noAccess == Csla.Security.NoAccessBehavior.ThrowException))
    
  5.       result = ReadProperty<P>(propertyInfo);
    
  6.     else
    
  7. result = propertyInfo.DefaultValue;
    
  8.     return result;
    
  9.   }
    

       7.另外一点,属性友好名称friend Name,如果有多语言需求,可以通过获取资源来实现.
    至于关系属性,SmartDate这些我们在遇到时再介绍,我们接着添加产品的验证规则,先只添加对编号,名称不为空的校验,以及长度的限制:

隐藏行号 复制代码 Product.BusinessRules
  1. #region  Business Rules
    
  2. protected override void AddBusinessRules()
    
  3. {
    
  4.     ValidationRules.AddRule(Csla.Validation.CommonRules.StringRequired,
    
  5.                             new Csla.Validation.RuleArgs(ItemNoProperty));
    
  6.     ValidationRules.AddRule(
    
  7.       Csla.Validation.CommonRules.StringMaxLength,
    
  8.        new Csla.Validation.CommonRules.MaxLengthRuleArgs(ItemNoProperty, 50));
    
  9. 
    
  10.     ValidationRules.AddRule(Csla.Validation.CommonRules.StringRequired,
    
  11.                           new Csla.Validation.RuleArgs(ItemNameProperty));
    
  12.     ValidationRules.AddRule(
    
  13.       Csla.Validation.CommonRules.StringMaxLength,
    
  14.        new Csla.Validation.CommonRules.MaxLengthRuleArgs(ItemNameProperty, 200));
    
  15. }
    
  16. #endregion
    

    基类里面维护了一个ValidationRules属性,专门存储验证规则,我们直接向这个集合里添加就行了,添加的规则可以是通用的一些规则,在CommentRules下面,有最大值最小值,长度,正则等通用规则.也可以是自定义自己的规则,比如我们需要规定所有的产品编号必须以字符开头,否则保存或者更新不成功:

隐藏行号 复制代码 Product.BusinessRules
  1. 
    
  2.       ValidationRules.AddRule<Product>(ItemNoRule, ItemNoProperty);
    
  3.   }
    
  4. 
    
  5. 
    
  6.   private static bool ItemNoRule<T>(
    
  7. T target, Csla.Validation.RuleArgs e) where T : Product
    
  8. {
    
  9.       if (!string.IsNullOrEmpty(target.ReadProperty(ItemNoProperty)) && !char.IsLetter(target.ReadProperty(ItemNoProperty)[0]))
    
  10.       {
    
  11.           e.Description = "编号必须以字母开头!";
    
  12.           return false;
    
  13.       }
    
  14.       else
    
  15. {
    
  16.           return true;
    
  17.       }
    
  18.   }
    

    这样当我们更新或者保存产品时,如果产品编号不是以字符开头,就会出异常,在业务对象的BrokenRulesCollection属性里加入导致失败的规则,我们可以直接查找到描述的错误信息。具体CSLA在内部是怎么调用的,我们会在后面介绍。其实之CSLA之所以让你感觉他的属性,他的业务方法,数据门户,业务规则,权限之间相互比较解耦,是因为他们之间的调用已经在框架部门,在CSLA的代码里面内部调用了。好了,睡了,今天就到这里,下一节添加数据门户的实现和基本工厂方法。

 代码下载

作者:孤独侠客似水流年
出处:http://lonely7345.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 

posted @ 2010-02-04 00:58  孤独侠客  阅读(8438)  评论(11编辑  收藏  举报