更具体地说,假设我们有一个按属性P1和P2排序的集合,如下所示:
在通过收藏品进行预告时,我希望在房产发生变化时收到通知 因此,对于P1,我需要按以下特定顺序发出以下4个通知:
对于P2,这将发出12个通知,让我不在列表中。
当然,我可以在每个用例中通过在foreach循环中保存“旧”属性值(OldP1 = P1)并在P1!= OldP1时触发事件/执行方法来执行此操作,但这不可重用。
是否有一个已经实现此模式的集合?
如果没有,任何建议如何让它更可重复使用?
编辑:注意,我只是想在foreach循环中得到通知,如果某个属性值与上一次迭代中的属性值不同,这与INotifyPropertyChanged等无关。
答案 0 :(得分:1)
.NET有ObservableCollection<T>
,但用于观察存储的对象和集合本身发生的变化。你的收藏品没有变化(假设你理解正确的话) - 你只是想在循环期间得到通知,如果某些属性值与之前的迭代不同。
在可重用代码方面可能指向正确方向的东西:
public class PropertyWatcher<TSource>
{
// initialization code omitted
private Dictionary<string, object> previousValues;
private Dictionary<string, Func<TSource, object>> selectors;
public void RegisterWatcher<TSource>(Func<TSource, object> propertySelector,
string propertyName)
{
this.selectors.Add(propertyName, propertySelector);
this.previousValues.Add(propertyName, null);
}
public void NotifyIfDifferent<TObject, TPropertyType>(TSource currentItem)
{
foreach (var key in this.selectors.Keys)
{
var selector = this.selectors[key];
var currentValue = selector(currentItem);
if (!currentValue.Equals(this.previousValues[key]))
{
// raise notification, event; antyhing to your liking
}
this.previousValues[key] = currentValue;
}
}
}
并且,假设我们正在处理您提到的P1
和P2
属性,那么使用情况将如下所示:
var list = new List<SomeObject>(); // list of items you intend to watch
var watcher = new PropertyWatcher<SomeObject>();
watcher.RegisterWatcher((SomeObject o) => o.P1, "P1");
watcher.RegisterWatcher((SomeObject o) => o.P2, "P2");
foreach (var item in list)
{
watcher.NotifyIfDifferent(item);
}
这绝不是完整的解决方案。它应该在涉及简单值时起作用(因此.Equals
可以轻松处理比较)。当然,您仍然需要向PropertyWatcher
类添加一些事件,并且可能会在这里和那里进行调整 - 但我认为一般的想法很容易理解。
对于更高级的方案,我认为您必须采用更通用的方法。
答案 1 :(得分:0)
不确定C#是否有方面,但这可能是一个值得关注的地方。否则,您可以将更改委托添加到您的类,然后在属性方法的set部分中,您可以调用委托:
private delegate void beforeGroup( MyObject current, MyObject changesTo );
private delegate void afterGroup( MyObject current, MyObject changedFrom );
public MyObject P1 {
get {
return p1;
}
set {
beforeGroup( p1, value );
MyObject oldValue = p1;
p1 = value;
afterGroup( p1, oldValue );
}
}