我正在尝试生成生成的事件,我正在创建一个合并两种类型事件的流。我正在监视一组记录,如果
,事件可能会触发
1.添加/删除行时的CollectionChangedEvent。
2.当项目的某个值发生变化时,PropertyChangedEvent
public IObservable<IEnumerable<ChangeDTO>> GetChangeStream()
{
IObservable<IEnumerable<ChangeDTO>> allItems =
Observable.FromEventPattern<CollectionChangedEventArgs>(
x => source.CollectionChanged += x,
x => source.CollectionChanged-= x)
.Select(i => new ChangeDTO(source.SelectedItems, true, null)})
.Buffer(Timespan.FromMilliSeconds(300);
IObservable<IEnumerable<ChangeDTO>> updatedItem =
Observable.FromEventPattern<PropertyChangedEventArgs>(
x => source.PropertyChanged += x,
x => source.PropertyChanged -= x).
Select(i => new List<ChangeDTO>() {new ChangeDTO(new[] {source.Item}, false, source.UpdatedProperties)};
return allItems.Merge(updatedItems);
}
public class ChangeDTO
{
ChangeDTO(IEnumerable<SourceDTO> items, bool recalculateAll, IEnumerable<string>
propertiesChanged)
}
我试图清除PropertyChangedEvent缓冲区,如果CollectionChangedEvent在300毫秒内触发,即对属性更改不感兴趣并想要忽略它们。只有在没有触发CollectionChangedEvent的情况下,才会对属性更改感兴趣。
答案 0 :(得分:2)
这有点牵扯,但我会试着简洁地解释一下!
核心思想是从缓冲的PropertyChangedEvents(PCE)流开始,但每次有CollectionChangedEvent(CCE)时都切换到新的缓冲流。最后,我们将CCE和扁平缓冲的PCE流合并在一起。
我们通过将CCE转换为Unit.Default
和StartWith
的初始值来启动collectUpdateItems(这让我们可以在第一个CCE之前开始收集PCE)。然后将每个脉冲项目(Select
)投射到新的缓冲PCE流中。 Switch
将确保仅返回最新的缓冲区流。 Where
只会删除空缓冲区。
最后我们Merge
使用原始CCE流(投射到单个元素列表中以与PCE缓冲区兼容)。
希望这是有道理的!
稍微修改您的流以使用简单,无缓冲的ChangeDTO对象流开始:
IObservable<IEnumerable<ChangeDTO>> allItems =
Observable.FromEventPattern<CollectionChangedEventArgs>(
x => source.CollectionChanged += x,
x => source.CollectionChanged-= x)
.Select(i => new ChangeDTO(source.SelectedItems, true, null)});
IObservable<IEnumerable<ChangeDTO>> updatedItem =
Observable.FromEventPattern<PropertyChangedEventArgs>(
x => source.PropertyChanged += x,
x => source.PropertyChanged -= x).
.Select(i => new ChangeDTO(new[] {source.Item}, false, source.UpdatedProperties));
var collectUpdatedItems = allItems
// We only need to know the CCE happened, not the details of it, so convert to Units
.Select(_ => Unit.Default)
// We must insert an event so PCEs are buffered before the first CCE
.StartWith(Unit.Default)
// Here we create a new PCE buffer stream at the start and after each CCE
.Select(_ => updateItem.Buffer(TimeSpan.FromMilliseconds(300)))
// On a CCE, switch to the new PCE buffer stream, dropping the current PCE buffer
.Switch()
// Finally drop any empty buffers
.Where(i => i.Count > 0);
// merge the CollectionChangedEvents with the PropertyChangedEvent buffers
return collectionUpdateItems.Merge(allItems.Select(i => new List<ChangeDTO> {i}));