今天在园子里看到一篇非常不错的文章,其中一句对是对加班与时间的说法:“没钱的人,时间就是你的财富.有钱人把钱花出去,得到收益.穷人把时间撒出去,也可以得到收益.”,看完后感受颇深,在这分享给大家:Href
回味过去一年的学习,很多的时候都是围绕着csla框架,从中汲取的一些想法及感受,刚看到桌上的两本csla的书(2005与2008),就翻开看了几页,正巧看到了属性一章,对于属性的一些学习回忆,一些想法,希望能给.net/C#初学者一些帮助。
csla框架中以一定的规则定义了很多功能的实现方式,其中很多的功能都是在封装属性的过程中实现的,诸如数据有效性验证,数据访问权限控制,以及之后的数据绑定的更新,总之,属性是作为外界访问对象数据的入口。
先从05的版本中回味一下属性长的样子:
1: private string _name = string.Empty;
2: public string Name
3: {
4: get
5: {
6: CanReadProperty(true);
7: return _name;
8: }
9: set
10: {
11: CanWriteProperty(true);
12: if (value == null) value = string.Empty;
13: if (_name != value)
14: {
15: _name = value;
16: PropertyHasChanged();
17: }
18: }
19: }
从各方法的名称中就可以很显示的看出,无论是属性的获取和设置都调用了一些方法,当然这些方法是根据各自的情况可选择的,甚至还会添加更多的代码。在2.0中大多数的属性都类似这样,上述代码中CanReadProperty与CanWriteProperty反应了框架对数据字段操作权限的验证,PropertyHasChanged也实现了数据有效性验证、对象状态跟踪以及错误跟踪。平日中并不知道,或者说并未了解不直接引用字段而用属性对字段进行封装到底是为了什么,单单是因为OO而OO吗!以前确定有那么点意思,自己也是从上面这段代码中感受到的,属性并非只是控制可读、可写,这里还有很多东西可以让我们想象。
再贴一下3.8中的属性模样:
1: private static PropertyInfo<string> NameProperty =
2: RegisterProperty<string>(o => o.Name, "名称");
3: public string Name
4: {
5: get { return GetProperty(NameProperty); }
6: set { SetProperty(NameProperty, value); }
7: }
新版本中的属性样子好多了,但实现功能与旧版本是一至的,不过把大多数的硬代码写在了框架内部,而且框架添加了字段管理的功能,对于带有父子关系的复杂对象来说更加方便的管理其对象状态(所以,在调用对象的Save(方法时,框架会自动根据子对象的状态来调用子对象的数据库操作方法)。
框架中的另一重要功能也是在属性内部进行操作,也就是延迟加载功能,在框架中以及PoEAA中都是看到,在复杂对象(包含有子对象的对象)的创建与加载,特别是对象的数据加载过程中,最好能够加载正好够用的数据,所以,(自己感觉)对于使用频率高的子对象,加载根对象的过程中一起加载子对象,而对于使用频率不高的对象可以考虑使用延迟加载。在属性的中体现为根对象只持有子对象的空引用,当系统调用属性时,再确定是否加载子对象,在csla框架也有体现,如下:
1: private static PropertyInfo<AddressInfoECL> AddressInfoECLProperty =
2: RegisterProperty<AddressInfoECL>(o => o.AddressInfos, "配送地址");
3: public AddressInfoECL AddressInfos
4: {
5: get
6: {
7: if (!FieldManager.FieldExists(AddressInfoECLProperty))
8: {
9: LoadProperty(AddressInfoECLProperty,
10: ModFunc.AddressInfoECL.NewAddressInfoECL());
11: }
12: return GetProperty(AddressInfoECLProperty);
13: }
14: }
上面的get中就先从字段管理器里面判断是否存在当前字段信息,如果不存在,系统就去调用子对象的加载过程。
当然,属性复杂性也是与具体的需求相关,也许很多的情况下属性就是对字段的简单get.set封装,作为层与层之间对象的数据传递来使用。
最后,控制好属性的访问级别(特别是set)很重要!