代码改变世界

LINQ TO SQL学习笔记(3)_解决通用基类的循环引用问题

2009-04-02 11:11  宗哥  阅读(3079)  评论(5编辑  收藏  举报

解决通用基类的循环引用问题

续上一篇: http://www.cnblogs.com/Roping/archive/2009/04/01/1422404.html

在我们基于Domain驱动模式开发面向对象的多层架构的时候,层和层之间数据的传输对象(DTO)往往简化为领域对象模型,在上文中就是我们利用LINQ TO SQL对象设计器生成的Bill,Customer等实体类。

存在的问题

通常的做法,我们把这些实体类单独分成一层,这样程序分层划分成如下:

  • 数据访问层(Data Access Layer)
  • 业务层 (Business Layer)
  • 用户界面层(UI Layer)
  • 实体层(Entity Layer)

注意,多层应用程序,一般遵守这样的规则:UI调用BL,BL调用DL,不能跨级调用,也不能底层调用上层,但是实体层是我们的DTO,各个层都可以调用它。

  如果这样划分,我们系统就出现问题:

  我们把RepositoryBase划到数据层,LINQ TO SQL对象设计器生成的类分到实体层,数据层引用实体层,没有问题,但是我们看到,在我们实体层,存在一个方法(以Bill为例):

 

public static RepositoryBase<Bill, LINQtoSQLHelper.DataContextSetUp> CreateRepository() { return new BillRepository(); }

 

数据层也必须引用数据访问层,循环引用。另外,对于如何体现loadoption那?

解决循环引用

 以Bill实体为例,循环引用的病因在于Bill实体中添加这样一个方法:

public static RepositoryBase<Bill, LINQtoSQLHelper.DataContextSetUp> CreateRepository() { return new BillRepository(); }

 

为什么要添加这个方法那?这样做就是充血模式的实体了。注意到RepositoryBase.cs有一段代码:

 

Code

 

作者添加这段代码,主要是利用反射获取当前实体的CreateRepository方法,实现对象的CRUD操作。如果实体中去掉这个CreateRepository方法,那这段代码如何变通,请看:

dd

try

                            {

                                
object Repository = association.OtherType.Type.GetMethod("CreateRepository").Invoke(nullnull);

                                Repository.GetType().GetMethod(
"IterateEntitySet",

                                                             BindingFlags.NonPublic 
| BindingFlags.Instance).Invoke(

                                    Repository,

                                    
new object[4]

                                    {

                                        AssociationProperty.GetValue(theEntity, 
null),

                                        context,

                                        OperationMode,

                                        Recursively

                                    }

                                    );

                            }

                            
catch (System.Reflection.TargetInvocationException e)

                            {

                                
throw (e.InnerException);

                            }

 

 主要利用反射,从当前数据访问层Assembly中获得对应实体类的的Repository类。

好,解决循环引用问题。

体现loadoption

这个问题比较棘手,确实在底层无法感知业务需求的东西,而其DataContext是共用的。

能不能另辟捷径那?注意我们用泛型构造RepositoryBase类,那能不能从中得到什么那?

我们对类RepositoryBase添加入如下方法

 

Code

 

,好,这个基本上体现loadoption。

源代码

  更新的源代码,本文可以找到这里

反馈!

本文是对我翻译上一篇文章的一个补从,代码你可以自由使用,但是必须声明出处。

;