我的应用程序中有多个业务对象(C#,Winforms,WinXP).当用户在UI上执行某些操作时,每个对象都会被应用程序的不同部分修改和更新.每次修改后,我需要先检查更改内容,然后记录对对象所做的更改.记录此信息的目的是创建对应用程序中正在进行的活动的全面跟踪.
这些对象中的许多对象包含其他对象的列表,并且此嵌套可以是多个级别.任何解决方案的两个主要要求是
- capture changes as accurately as possible
- keep performance cost to minimum.
例如,业务对象:
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...
我可以假设我可以访问对象的旧值和新值.
在这种情况下,我可以想到两种方法来尝试这样做而不被告知明确改变了什么.
- use reflection and iterate thru all properties of the object and compare
those with the corresponding
properties of the older object. Log
any properties that have changed. This
approach seems to be more flexible, in
that I would not have to worry if any
new properties are added to any of the
objects. But it also seems performance
heavy.- Log changes in the setter of all the properties for all the objects.
Other than the fact that this will
need me to change a lot of code, it
seems more brute force. This will be
maintenance heavy and inflexible if
some one updates any of the Object
Types. But this way it may also be
preformance light since I will not
need to check what changed and log
exactly what properties are changed.
建议采取任何更好的方法和/或改进上述方法
解决方法:
我可能无法给你一个好的答案,但我会告诉你,在绝大多数情况下,选项1不是一个好的答案.我们在项目中处理一个非常相似的反思“图形漫步者”;当时似乎是一个好主意,但这是一场噩梦,原因如下:
>你知道对象发生了变化,但是在反思的“变更处理”课程中,如果没有高水平的知识,关于它上面的对象的工作方式,你可能不知道为什么.如果该信息对您很重要,则必须将其提供给更改处理程序,大多数情况下;通过域对象上的字段或属性,需要更改域并向域提供有关业务逻辑的知识.
>更改可能会影响多个对象,但可能不需要每个级别的更改日志;例如,当批准新贷款时,客户可能不希望看到借款人在日志中的未偿还贷款计数发生变化,但他们确实希望看到由于合并而发生的变更.管理有关登录这些情况的规则需要更改处理类来了解更多的结构,而不仅仅是一个对象,这可以非常快速地使变更处理对象非常大,而且非常脆弱.
>图表助行器的要求可能比你知道的要多;如果您的对象图包含反向引用或交叉引用,则walker必须知道它的位置,并且最简单的综合方法是保留它所处理的对象列表,并在处理之前检查当前对象与其处理的对象(使反向回溯成为N ^ 2操作).它还必须不考虑对图中对象的更改,当您持久保存*(不是“级联”的引用)时,这些对象将不会被持久化. NHibernate使您能够插入自己的图形漫游器并遵守映射中的级联脚趾,这有所帮助,但是如果您使用的是自己动手的DAL,或者您想要将更改记录到对象中NHibernate不会级联到,你将不得不自己设置这一切.
>处理程序中的一段逻辑可能会进行更改,需要更新“父”对象(可能更新计算字段).现在,如果更改对另一部分更改处理逻辑感兴趣,则必须返回并重新评估更改的对象.
>如果你有需要创建和持久化新对象的逻辑,你必须做两件事之一;将新对象附加到某个地方的图形(其中可能会或可能不会被walker拾取),或者将新对象保留在其自己的事务中(如果您使用的是ORM,则该对象无法引用另一个对象)具有“级联”设置的图形,将导致首先保存它.
>最后,在处理图形和查找特定对象的“处理程序”时都具有高度反射性,将复杂树传递到这样的框架中是应用程序中保证的速度缓冲.
如果您跳过“更改处理程序”反射模式,并且在您在业务中执行的“工作单元”中包含审计日志或任何预先持久性逻辑的创建,我认为您将为自己省去很多麻烦层,通过一组“审计记录器”.这允许进行更改的逻辑使用算法选择模式(如命令或策略)来告诉您的审计框架确切地发生了哪种更改,因此它可以选择将生成所需日志消息的记录器.