捕获对象属性的更改

时间:2010-09-29 15:15:40

标签: c# enterprise audit

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

这些对象中的许多对象包含其他对象的列表,并且此嵌套可以是多个级别的深度。任何解决方案的两个主要要求是

  
      
  1. 尽可能准确地捕捉变化
  2.   
  3. 将性能成本降至最低。
  4.   

例如业务对象:

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...

我可以假设我可以访问对象的旧值和新值。

在这种情况下,我可以想到两种尝试这样做的方法,而不会被告知明确改变了什么。

  
      
  1. 使用反射并通过对象的所有属性进行迭代并进行比较   那些与之对应的   旧对象的属性。日志   任何已更改的属性。这个   方法似乎更灵活,在   如果有的话,我不必担心   新属性被添加到任何   对象。但它似乎也表现出色   重。
  2.   
  3. 记录所有对象的所有属性的setter中的更改。   除了这样的事实   需要我改变很多代码,它   似乎更蛮力。这将会   维护沉重而且不灵活   有人会更新任何对象   类型。但这种方式也可能   因为我不会这样做   需要检查更改和记录的内容   究竟改变了哪些属性。
  4.   

建议采取任何更好的方法和/或改进上述方法

3 个答案:

答案 0 :(得分:3)

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

最佳方法称为Aspect-Oriented Programming或AOP。您将“建议”注入setter和getter(实际上所有方法执行,getter和setter都只是特殊方法),允许您“拦截”对对象执行的操作。查看{A {3}}或Spring.NET了解.NET AOP解决方案。

答案 1 :(得分:2)

我可能无法给你一个好的答案,但我会告诉你,在绝大多数情况下,选项1不是一个好的答案。我们在项目中处理一个非常相似的反思“图形漫步者”;当时似乎是一个好主意,但这是一场噩梦,原因如下:

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

如果您跳过“更改处理程序”反射模式,并且在您正在执行的“工作单元”中包含审计日志或任何预先持久性逻辑的创建,我认为您将为自己省去很多麻烦在业务层,通过一组“审计记录器”。这允许进行更改的逻辑使用算法选择模式(如命令或策略)来告诉您的审计框架确切地发生了哪种更改,因此它可以选择将生成所需日志消息的记录器。

答案 2 :(得分:0)

请点击此处adempiere如何更改日志:http://wiki.adempiere.net/Change_Log