2010-09-29 106 views
4

我的应用程序中有多个业务对象(C#,Winforms,WinXP)。当用户在UI上执行某些操作时,这些对象中的每一个都会被应用程序的不同部分修改和更新。每次修改后,我需要首先检查已更改的内容,然后记录对对象所做的更改。记录这个目的是为了创建一个对应用程序中正在进行的活动的全面跟踪。捕获对象属性的更改

这些对象中包含许多包含其他对象的名单,这嵌套可以几个层次深。对于任何解决方案的两个主要要求是

  1. 捕捉尽可能准确地
  2. 保持性能成本最低的变化。

如业务对象:

public class MainClass1 
{ 
    public MainClass1() 
    { 
     detailCollection1 = new ClassDetailCollection1(); 
     detailCollection2 = new ClassDetailCollection2(); 
    } 

    private Int64 id; 
    public Int64 ID 
    { 
     get { return id; } 
     set { id = value; } 
    } 

    private DateTime timeStamp; 
    public DateTime TimeStamp 
    { 
     get { return timeStamp; } 
     set { timeStamp = value; } 
    } 

    private string category = string.Empty; 
    public string Category 
    { 
     get { return category; } 
     set { category = value; } 
    } 

    private string action = string.Empty; 
    public string Action 
    { 
     get { return action; } 
     set { action = value; } 
    } 

    private ClassDetailCollection1 detailCollection1; 
    public ClassDetailCollection1 DetailCollection1 
    { 
     get { return detailCollection1; } 
    } 

    private ClassDetailCollection2 detailCollection2; 
    public ClassDetailCollection2 DetailCollection2 
    { 
     get { return detailCollection2; } 
    } 

    //more collections here 
} 

public class ClassDetailCollection1 
{ 
    private List<DetailType1> detailType1Collection; 
    public List<DetailType1> DetailType1Collection 
    { 
     get { return detailType1Collection; } 
    } 

    private List<DetailType2> detailType2Collection; 
    public List<DetailType2> DetailType2Collection 
    { 
     get { return detailType2Collection; } 
    } 
} 

public class ClassDetailCollection2 
{ 
    private List<DetailType3> detailType3Collection; 
    public List<DetailType3> DetailType3Collection 
    { 
     get { return detailType3Collection; } 
    } 

    private List<DetailType4> detailType4Collection; 
    public List<DetailType4> DetailType4Collection 
    { 
     get { return detailType4Collection; } 
    } 
} 

//more other Types like MainClass1 above... 

我可以假设,我将有机会获得旧值和对象的新值。

在这种情况下,我能想到的2种方式,试图做到这一点没有被告知哪些已明确改变。

  1. 使用反射和迭代通的对象的所有属性和比较 那些与老对象的相应属性 。日志 已更改的任何属性。这 方法似乎更加灵活, ,我不会担心,如果任何 新属性添加到任何 对象。但它也似乎表现沉重。
  2. 在setter中记录所有对象的所有属性的更改。 除了这个将 需要我改变很多代码的事实外,它似乎更加蛮力。这将是 维护繁重和不灵活,如果 某人更新任何对象 类型。但这种方式也可能是 性能与光,因为我不会 需要检查哪些改变和日志 性质被改变什么。

建议以上述方法更好的方法和/或改进,欢迎

+0

我写了一个reflction为基础,但预编译单个对象(对)比较器这样回答。所以它可以做得相对便宜。打开弓,不能看 - 但会尝试稍后找到它。 – 2010-09-29 15:20:14

回答

2

我可能无法给你一个很好的答案,但我要告诉你的是,在绝大多数情况下,选项1是不是一个很好的答案。在我们的项目中,我们正在处理一个非常类似的反射式“图形漫步者”;似乎是在当时是个好主意,但它是一个噩梦,有以下原因:

  • 你知道对象改变了,但没有关于运作反射“变化处理”一流的知识水平高上面的物体,你可能不知道为什么。如果这些信息对您很重要,您必须将其交给更改处理程序,大多数情况下都可以通过域对象上的字段或属性进行更改,从而要求更改您的域并向域传授有关业务逻辑的知识。
  • 更改可能会影响多个对象,但可能不希望在每个级别记录更改;例如,当新贷款被批准时,客户可能不希望在日志中看到借款人尚未偿还贷款的变化,但他们确实希望看到由于合并而导致的变化。在这些情况下管理有关登录的规则需要更改处理类才能知道更多的结构,而不仅仅是一个对象,这可以很快地使变更处理对象变得非常大而且非常脆弱。
  • 您的图形漫步者的要求可能比您知道的要多;如果您的对象图包含反向引用或交叉引用,那么Walker必须知道它的位置,最简单的综合方法是保存处理对象的列表,并检查当前对象与处理对象之前处理的对象(使反向追踪N^2操作)。它也不能考虑对图中对象的更改,当持久保存最高级别(不是“级联”的引用)时,该对象不会被保留。 NHibernate使您能够插入自己的图形漫步者并遵守映射中的级联rukles,这有助于实现,但如果您使用的是自己的DAL,或者您想将更改记录到对象NHibernate不会级联,你将不得不自己设置这一切。
  • 处理程序中的一段逻辑可能做出需要更新“父”对象(可能更新计算字段)的更改。现在,如果更改对另一部分更改处理逻辑感兴趣,则必须返回并重新评估更改的对象。
  • 如果您有需要创建和持续新对象的逻辑,则必须执行以下两项操作之一;将新对象附加到图形的某处(可能或不可能被walker拾取),或者将新对象保存在自己的事务中(如果使用的是ORM,则该对象不能从另一个对象引用对象带有“级联”设置的图表会导致首先保存)。
  • 最后,在漫游图形和查找特定对象的“处理程序”方面具有高度反射性,将复杂的树传递到此类框架中可以保证在应用程序中减速。

我想你会为自己省下很多麻烦,如果你跳过“更改处理”反射模式,包括在审计日志或任何持久性预逻辑的创造“的工作单元”你”通过一组“审计记录器”重新在业务层进行。这使得进行更改的逻辑可以使用诸如Command或Strategy之类的算法选择模式来告诉审计框架究竟发生了什么样的改变,因此它可以选择将生成所需日志消息的记录器。

+0

我最终采用了第二种方法的混合体。我现在保存所有创建和删除的更改,并查询数据库以查看比较和记录更改的对象以前的状态。 – EndlessSpace 2010-11-17 20:44:41

3

我在几年前开发这样的系统。这个想法是跟踪对象的变化并将这些变化存储在数据库中,例如对象的版本控制。

最好的办法是叫Aspect-Oriented Programming,或AOP。你向设置者和获取者注入“建议”(实际上所有的方法执行,获取者和设置者都只是特殊的方法),允许你“截取”对象所采取的行动。查看.NET AOP解决方案的Spring.NETPostSharp

+0

+1,我想你可以添加一个IsDirty setter作为建议。有没有办法为每个属性做到这一点,而不必通过整个属性列表并附加属性?有没有办法在命名空间中为所有类执行此操作? – user420667 2013-07-24 19:54:14