有没有办法在属性更改已排序集合中的组时收到通知?

时间:2011-11-12 18:54:21

标签: c# sorting collections notifications grouping

更具体地说,假设我们有一个按属性P1和P2排序的集合,如下所示:

  • A 1
  • A 2
  • A 2
  • A 3
  • B 1
  • B 1
  • B 2
  • B 3

在通过收藏品进行预告时,我希望在房产发生变化时收到通知 因此,对于P1,我需要按以下特定顺序发出以下4个通知:

  1. OnBeforeGroup(P1,“A”)
  2. OnAfterGroup(P1,“A”)
  3. OnBeforeGroup(P1,“B”)
  4. OnAfterGroup(P1,“B”)
  5. 对于P2,这将发出12个通知,让我不在列表中。

    当然,我可以在每个用例中通过在foreach循环中保存“旧”属性值(OldP1 = P1)并在P1!= OldP1时触发事件/执行方法来执行此操作,但这不可重用。

    是否有一个已经实现此模式的集合?
    如果没有,任何建议如何让它更可重复使用?

    编辑:注意,我只是想在foreach循环中得到通知,如果某个属性值与上一次迭代中的属性值不同,这与INotifyPropertyChanged等无关。

2 个答案:

答案 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;
        }
    }
}

并且,假设我们正在处理您提到的P1P2属性,那么使用情况将如下所示:

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 );
    }
}