浅谈C#中的延迟加载(3)还原模型的业务规则

  上一篇文章讲到把实体类中需要实现延迟加载的属性声明为virtual,然后继承实体类做一个子类,在子类里面实现该属性,配合使用委托来实现比较完美的延迟加载(原本的模型层依旧保持在最底层用于贯穿三层结构,同时又可以实现在实体类的属性里面访问到比他高层的数据访问层)。文章的最后依旧出现杯具,原因是在对模型的属性实现延迟加载之前,这个属性可能由于我们业务的需要,它并不单单是作为一个存储和读取的功能使用,而是在其get或者set的访问器中都包含这或许复杂或许简单的逻辑代码。

  举例:考虑一下这个情景,我们有一个叫做任务单的实体类,其中有两个属性,一个叫做任务名,一个叫做发布时间,现在有这样的业务规定,任务名称可以为空,但如果任务名称为空的话我们要读取发布时间生成一个任务名来代替掉这个空值(例如叫做Issue20110120191345),当然这个例子有点牵强,主要是我想不出什么很具体的实例,但是在实际开发中这种情况肯定是有的并且其中的逻辑代码有可能复杂到你难以想象。

  沿用前面两篇文章的例子,我模拟了这一现象,对文章实体类做了点修改,增加了一个名为GetCategoryRecord的字符串型属性,它的作用基本上可以从字面上看出来,叫做Category属性get访问器调用记录。于是文章类(基类)修改如下:

c#代码

namespace Model

{

// 文章实体类

public class Article

{

public int ArticleID { get; set; }

public string Title { get; set; }

public string Cotnent{ get; set; }

public DateTime CreateTime { get; set; }

public int CategoryID { get; set; }

/// <summary>

/// 所属分类

/// </summary>

protected Model.ArticleCategory _category;

/// <summary>

/// 所属分类

/// </summary>

public virtual Model.ArticleCategory Category

{

get

{

GetCategoryRecord += "
获取分类;";

return _category;

}

}

/// <summary>

/// Category属性get访问器调用记录

/// </summary>

public string GetCategoryRecord { get; set; }

}

}

  这里我们关心那两个有写注释的属性,并且出现了一个保护字段_category(这个尤其重要,起到和子类的联通作用)。可以看到现在有这样的业务规则了:Category属性被get一次就会往GetCategoryRecord属性中做点记录。于是我们在设计代码的时候立刻会想到要是继承Model.Article类的基类要是重写这个属性的话势必要保持这个业务不变,否则在实现延迟加载之后肯定会丢掉一些之前设计好的业务逻辑了。修改继承它的子类如下:

c#代码

namespace DModel

{

/// <summary>

/// 文章

/// </summary>

public class Article : Model.Article

{

/// <summary>

/// 所属分类

/// </summary>

public override Model.ArticleCategory Category

{

get

{

if (base._category == null)

{

if (CategoryLazyLoader != null)

{

base._category = CategoryLazyLoader(CategoryID);

}

else

{

base._category = null;

}

}

return base.Category;

}

}

/// <summary>

/// 文章分类延时加载器(委托)

/// </summary>

public Func<int, Model.ArticleCategory> CategoryLazyLoader { get; set; }

}

}

  这里可以看到DModel.Article类的Category属性中对基类的保护字段base._cateogry进行了操作,最后返回的是基类Category。粗看起来似乎有点乱,但是理清一下思路其实如下:基类的Category属性通过返回_category字段的方式返回值,也就是说数据是存在_category字段而不是属性中,但是_category字段怎么才会有值呢,那就是在子类里面通过调用委托拿来的,而这个属性在子类里面不是直接返回的,而是调用基类来返回,这样一来,调用到子类的Category属性的get访问器的时候,先对基类的_categoty字段赋值,然后调用基类的Category属性执行了一些逻辑代码,最后成功地把(已经被赋值的)基类的_categoty字段给返回去。而这一切都是在前面我们实现好的延迟加载的基础上完成的。总结成几个字就是:子类负责延时加载,基类赋值数据存储和返回!呵呵,是不是觉得很简单呢。

这里可以看到DModel.Article类的Category属性中对基类的保护字段base._cateogry进行了操作,最后返回的是基类Category。粗看起来似乎有点乱,但是理清一下思路其实如下:基类的Category属性通过返回_category字段的方式返回值,也就是说数据是存在_category字段而不是属性中,但是_category字段怎么才会有值呢,那就是在子类里面通过调用委托拿来的,而这个属性在子类里面不是直接返回的,而是调用基类来返回,这样一来,调用到子类的Category属性的get访问器的时候,先对_categoty字段赋值,然后调用基类的Category属性实现了一些逻辑代码,最后成功地把(已经被赋值的)_categoty字段给返回去。而这一切都是在前面我们实现好的延迟加载的基础上完成的。呵呵,是不是觉得很简单呢^^这里可以看到DModel.Article类的Category属性中对基类的保护字段base._cateogry进行了操作,最后返回的是基类Category。粗看起来似乎有点乱,但是理清一下思路其实如下:基类的Category属性通过返回_category字段的方式返回值,也就是说数据是存在_category字段而不是属性中,但是_category字段怎么才会有值呢,那就是在子类里面通过调用委托拿来的,而这个属性在子类里面不是直接返回的,而是调用基类来返回,这样一来,调用到子类的Category属性的get访问器的时候,先对_categoty字段赋值,然后调用基类的Category属性实现了一些逻辑代码,最后成功地把(已经被赋值的)_categoty字段给返回去。而这一切都是在前面我们实现好的延迟加载的基础上完成的。呵呵,是不是觉得很简单呢^^

  其实这一篇讲的情况不是针对延迟加载这个技术来讲的,在我们的开发过程中经常会遇到这种实现了业务代码的实体类属性,拥有这种属性的模型通常被叫做充血模型,如果模型的属性都是简单的get和set的话通常叫做贫血模型(当然可能有其他叫法 哈~)。这篇文章是在没啥内容,算是对前两篇文章的一个补充吧,希望没有浪费你的时间哈^_^。

时间: 2024-08-01 19:10:34

浅谈C#中的延迟加载(3)还原模型的业务规则的相关文章

浅谈C#中的延迟加载(2)善用virtual

之前的文章"浅谈C#中的延迟加载(1)--善用委托"中介绍了三层结构中在Model层对实体类的属性实现延迟加载的方法,该方法利用C#中的委托来实现,最后虽然延迟加载的目的得以实现,但是给客户端(例如UI层)暴露了不必要的属性(一个委托对象,我使用了泛型的Fun类来实现).这篇文章介绍一种方法来隐藏这个属性,同时又可以达到延迟加载的目的,更重要的是这一切都是在之前的基础上来完成的,不需要改变原来使用到实体类的地方的代码. 按照惯例,我们考虑一下想要我们的代码达到什么效果:首先在Model

一起谈.NET技术,浅谈C#中的延迟加载(2)——善用virtual

之前的文章"浅谈C#中的延迟加载(1)--善用委托"中介绍了三层结构中在Model层对实体类的属性实现延迟加载的方法,该方法利用C#中的委托来实现,最后虽然延迟加载的目的得以实现,但是给客户端(例如UI层)暴露了不必要的属性(一个委托对象,我使用了泛型的Fun类来实现).这篇文章介绍一种方法来隐藏这个属性,同时又可以达到延迟加载的目的,更重要的是这一切都是在之前的基础上来完成的,不需要改变原来使用到实体类的地方的代码. 按照惯例,我们考虑一下想要我们的代码达到什么效果:首先在Model

一起谈.NET技术,浅谈C#中的延迟加载(3)——还原模型的业务规则

上一篇文章讲到把实体类中需要实现延迟加载的属性声明为virtual,然后继承实体类做一个子类,在子类里面实现该属性,配合使用委托来实现比较完美的延迟加载(原本的模型层依旧保持在最底层用于贯穿三层结构,同时又可以实现在实体类的属性里面访问到比他高层的数据访问层).文章的最后依旧出现杯具,原因是在对模型的属性实现延迟加载之前,这个属性可能由于我们业务的需要,它并不单单是作为一个存储和读取的功能使用,而是在其get或者set的访问器中都包含这或许复杂或许简单的逻辑代码. 举例:考虑一下这个情景,我们有

浅谈C#中的延迟加载(3)——还原“.NET研究”模型的业务规则

上一篇文章讲到把实体类中需要实现延迟加载的属性声明为virtual,然后继承实体类做一个子类,在子类里面实现该属性,配合使用委托来实现比较完美的延迟加载(原本的模型层依旧保持在最底层用于贯穿三层结构,同时又可以上海企业网站制作实现在实体类的属性里面访问到比他高层的数据访问层).文章的最后依旧出现杯具,原因是在对模型的属性实现延迟加载之前,这个属性可能由于我们业务的需要,它并不单单是作为一个存储和读取的功能使用,而是在其get或者set的访问器中都包含这或许复杂或许简单的逻辑代码. 举例:考虑一下

一起谈.NET技术,浅谈C#中的延迟加载(1)——善用委托

很久以前就听过延迟加载这个东西,不过没有理解是什么意思,现在算是了解一二了,写点文章作为读书笔记,把自己的想法记录一下,希望对初学者帮助,不管是初学者或者高手如果发现文章那里写得不好或者有更好的思路和做法记得告诉我哦^^.文章打算写成两三篇,这个是第一篇. 在三层结构中我们通常会使用多一个叫做模型层的东西,这一层中最主要做的事情是把数据库中的表 (或者其他数据源,例如xml或者自己定义的一种数据格式)转成对应的类,例如有一个文章表,这时候在这一层就会有一个文章类:文章类的属性对应着文章表的列,例

浅谈C#中的延迟加载(1)善用委托

很久以前就听过延迟加载这个东西,不过没有理解是什么意思,现在算是了解一二了,写点文章作为读书笔记,把自己的想法记录一下,希望对初学者帮助,不管是初学者或者高手如果发现文章那里写得不好或者有更好的思路和做法记得告诉我哦^^.文章打算写成两三篇,这个是第一篇. 在三层结构中我们通常会使用多一个叫做模型层的东西,这一层中最主要做的事情是把数据库中的表 (或者其他数据源,例如xml或者自己定义的一种数据格式)转成对应的类,例如有一个文章表,这时候在这一层就会有一个文章类:文章类的属性对应着文章表的列,例

浅谈C#中的延“.NET研究”迟加载(2)——善用virtual

之前的文章"浅谈C#中的延迟加载(1)--善用委托"中介绍了三层结构中在Model层对实体类的属性实现延迟加载的方法,该方法利用C#中的委托来实现,最后虽然延迟加载的目的得以实现,但是给客户端(例如UI层)暴露了不必要的属性(一个委托对象,我使用了泛型的Fun类来实现).这篇文章介绍一种方法来隐藏这个属性,同时又可以达到延迟加载的目的,更重要的是这一切都是在之前的基础上来完成的,不需要改变原来使用到实体类的地方的代码. 按照惯例,我们考虑一下想要我们的代码达到什么效果:首先在Model

浅谈Python中copy()方法的使用

  这篇文章主要介绍了浅谈Python中copy()方法的使用,Python中的拷贝分为潜拷贝和深拷贝,本文只是简单介绍用法,需要的朋友可以参考下 copy()方法返回字典的浅拷贝. 语法 以下是copy()方法的语法: ? 1 dict.copy() 参数 NA 返回值 此方法返回字典的浅拷贝. 例子 下面的例子显示了copy()方法的使用. ? 1 2 3 4 5 6 #!/usr/bin/python   dict1 = {'Name': 'Zara', 'Age': 7};   dict

浅谈ASP中Request对象获取客户端数据的顺序

request|对象|客户端|数据 浅谈ASP中Request对象获取客户端数据的顺序 /**描述:在使用ASP Request对象时需要注意的小问题作者:慈勤强Email : cqq1978@yeah.net**/ 在ASP中Request对象是获取客户端提交数据的一个很重要的对象,大家对他也是非常熟悉了.虽然如此,还是经常有人问我下面的几种写法有什么不同,到底应该怎么写?strMessage = Request("msg")strMessage = Request.Form(&qu