наблюдатель на коллекции - PullRequest
7 голосов
/ 18 января 2011

Я делаю свои первые шаги в средах Rx на .net 4. я пытаюсь наблюдать коллекцию как List<int> или Dictionary<x,x>. и когда элемент добавляется в коллекцию, он записывает его ToString() в консоли.

есть идеи? или некоторые примеры кода спасибо

Ответы [ 3 ]

11 голосов
/ 18 января 2011

List<T> и Dictionary<TKey, TValue> не наблюдаемы (они не вызывают события, когда они изменяются), поэтому Rx не за что зацепиться.

Для List вы можете использовать ObservableCollection<T>, но вам нужно будет обернуть его события, чтобы использовать его из Rx.Вот пример использования методов расширения:

public static class ObservableCollectionExtensions
{
    public static IObservable<IEvent<NotifyCollectionChangedEventArgs>> 
        GetObservableChanges<T>(this ObservableCollection<T> collection)
    {
        return Observable.FromEvent<
            NotifyCollectionChangedEventHandler, NotifyCollectionChangedArgs>(
                h => new NotifyCollectionChangedEventHandler(h),
                h => collection.CollectionChanged += h,
                h => collection.CollectionChanged -= h
            );
    }

    public static IObservable<T> GetObservableAddedValues<T>(
        this ObservableCollection<T> collection)
    {
        return collection.GetObservableChanges()
            .Where(evnt => evnt.EventArgs.Action == NotifyCollectionChangedAction.Add)
            .SelectMany(evnt => evnt.EventArgs.NewItems.Cast<T>());
    }
}

Я добавил дополнительного помощника, который отображает только добавленные элементы как IObservable<T>, который вы можете использовать следующим образом:

ObservableCollection<int> collection = 
    new ObservableCollection<int>(new int[] { 1, 2, 3 });

collection.GetObservableAddedValues().Subscribe(
    i => Console.WriteLine("{0} was added", i)
);

В фреймворке нет наблюдаемого Словаря, хотя проект кодексного кода *1016* ObservableDictionary, по-видимому, заполняет этот пробел, и я уверен, что он может быть заключен аналогичным образом.

1 голос
/ 11 июля 2018

Для тех, у кого нет возможности использовать интерфейс IEvent, можно использовать FromEventPattern вместо:

public static class ObservableCollectionExtensions
{
    public static IObservable<EventPattern<NotifyCollectionChangedEventArgs>>
    GetObservableChanges<T>(this ObservableCollection<T> collection)
    {
        return Observable.FromEventPattern<
            NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
                h => collection.CollectionChanged += h,
                h => collection.CollectionChanged -= h
            );
    }

    public static IObservable<T> GetObservableAddedValues<T>(
        this ObservableCollection<T> collection)
    {
        return collection.GetObservableChanges()
            .Where(evnt => evnt.EventArgs.Action == NotifyCollectionChangedAction.Add)
            .SelectMany(evnt => evnt.EventArgs.NewItems.Cast<T>());
    }
}
1 голос
/ 11 апреля 2011

Использование ReactiveCollection из ReactiveUI :

var c = new ReactiveCollection<int>();
c.Changed.Subscribe(x => Console.Writeln(x.Value);
c.Add(1);
...