2012-02-21 81 views
0

我有一个Web服务,它返回一个代表密集进程结果的复杂数据结构。为了使服务响应,该进程在异步任务中运行。将长期运行任务的结果与以前的结果进行比较

服务第一次被调用时,返回一个空的数据结构并开始任务。随后的服务调用将返回缓存的数据,直到任务完成。完成后,我需要确定结果是否真的发生了变化。如果是这样,我更新一个属性,指出更新结果的日期/时间,并重置缓存数据,以便服务返回新结构。在未来某个时候,基于各种原因,任务重新启动并重复逻辑。

我正在寻找最有效的方式来确定结果是否已从“缓存”数据发生变化。最简单的方法是在结构中的每个对象上实现Equals,并根据子对象的等同性等进行父对等。因此,在根对象上调用Equals将产生所需的结果,但这需要爬行整个结构,我不确定这是最好的方法。

我也想过与原件及复印件启动和使用“IsDirty”标志,以表明在结构的对象发生了变化,但担心复制操作可以否定任何performce好处。

你会使用什么方法(以及为什么)?

回答

0

我会创建递归走到2个实例(左和右),其可任选地通过使用属性来控制的所有属性,并调用的遗留右equals方法的静态方法。当其中一个属性表示不等式时,我们知道这两个实例是不同的。这使我可以实现最小数量的代码进行比较,但完全可以控制比较的内容和比较方式(通过用[NoCompare]等新属性标记某些属性并实现自定义相等逻辑)。

+0

为什么这会比这些类自己实现Equals并执行简单的A == B检查更好? – SonOfPirate 2012-02-21 12:32:54

+0

@SonOfPirate - 这将在一个简单的类上工作,您只需要检查几个字段,并且只根据您的独有说明使用。默认情况下,平等是比较复杂的。尝试新的对象()==新的对象(),你会发现它会产生错误,因为地址空间不同(即使数据完全相同)。构建一个比较原子类递归的方法不会“违反”默认行为,并且更易于控制。 – Polity 2012-02-21 12:38:33

+0

实际上,Equals被设计为在代码中被重写以提供身份平等,所以你是正确的,Equals不会是最好的使用方法。 (例如,Hashtable使用Equals来确定两个项是否等价,使用基本实现来检查引用是否是同一个对象,这是很少需要的行为,MS添加了ReferenceEquals a,以便区分)。也就是说,我认为无论我称之为IsSameAs还是别的东西,在每个对象中封装“等价”标准都会更好。 – SonOfPirate 2012-02-21 13:30:25

0

假设您所提供的平等的经营者为您的数据对象,你应该能够只是检查检查,他们是平等的。

如:

class CacheEntry<TCacheItem> 
{ 
    TCacheItem item; 
    DateTime? lastUpated; 
} 

class MyItem 
{ 
    int Id; 
    string Foo; 

    public bool Equals(MyItem b) 
    { 
     return this.Id == b.Id && this.Foo == b.Foo; // or something like this... 
    } 
} 

然后,当你有你的结果返回:

CacheEntry<MyItem> cacheEntry = ...; 
    MyItem newItem = ...; 

    if (cacheEntry.Item != newItem) 
    { 
     cacheEntry.item = newItem; 
     cacheEntry.lastUpdated = DateTime.UtcNow; 
    } 

注:线程安全检查排除在外。

+0

是的,这看起来很简单,但需要时间爬过整个对象图来比较每个对象。 – SonOfPirate 2012-02-21 12:39:34

+0

我并不担心线程安全,因为当我到达这一点时,任何对象都不会改变。 – SonOfPirate 2012-02-21 12:40:05

+0

继上面的@Polity的帖子后,你会建议访问者处理抓取对象图,还是让对象的子对象的平等性等于它自己的平等检查? – SonOfPirate 2012-02-21 13:32:51