Реактивные расширения ... Примеры в приложении CRUD - PullRequest
4 голосов
/ 22 сентября 2011

Я только что вступил в борьбу с Reactive Extensions, но у меня до сих пор не было того момента "А-Ха", момента, когда все это, кажется, встало на свои места.В результате мне нужна некоторая помощь и желание узнать, какую роль могут иметь реактивные расширения в простой программе CRUD.

У кого-нибудь есть примеры того, как расширения RX помогли в их приложении CRUD.Как вы можете себе представить, я пишу приложение CRUD на C # ... принимаются любые примеры, и это опубликовано, чтобы я мог подумать о том, как RX может вписаться в тот тип программирования, которым я занимаюсь.

ВозможноВы могли бы перечислить, как программная задача выиграла от RX и как эта задача выполнялась до использования RX.

Ответы [ 6 ]

3 голосов
/ 22 сентября 2011

Я сделал такую ​​вещь, которая работала хорошо:

public interface IStorage : IDisposable
{
    IObservable<int> GetOperationsCount(IScheduler scheduler);

    IObservable<Node> FetchNodes(IObservable<NodeId> nodeIds, IScheduler scheduler);
    IObservable<Node> StoreNodes(IObservable<Node> nodes, IScheduler scheduler);
}

Это позволяет мне выполнять выборки и сохранения в фоновом потоке, а значения возвращать мне в потоке пользовательского интерфейса довольно легко.

Каждый вызов StoreNodes также устанавливает транзакцию, и я могу получить любые ошибки из наблюдаемой прибыли.

Я также использую наблюдаемую GetOperationsCount для отображения пользователю числаожидающие операции и т. д.

Мой личный опыт работы с Rx заставил меня захотеть использовать его для чего-либо асинхронного вообще - событий, начала / конца вызова, асинхронности, задач, потока и т. д. Это позволяет объединить всемодель и может быть значительным хранителем кода.

0 голосов
/ 10 января 2019

Rx отлично подходит для коллекций. Сейчас я не могу представить себе работу с языком, который не имеет LINQ-подобной функциональности.

В последнее время стало так же для Rx, в основном из-за библиотеки, которая использует Rx для LINQ: DynamicData

ReadOnlyObservableCollection<TradeProxy> list;

var myTradeCache = new SourceCache<Trade, long>(trade => trade.Id);
var myOperation = myTradeCache.Connect() 
        .Filter(trade=>trade.Status == TradeStatus.Live) 
        .Transform(trade => new TradeProxy(trade))
        .Sort(SortExpressionComparer<TradeProxy>.Descending(t => t.Timestamp))
        .ObserveOnDispatcher()
        .Bind(out list) 
        .DisposeMany()
        .Subscribe()

По сути, вы можете создавать LINQ-подобные запросы, которые динамически обновляются после любого изменения - нового элемента в исходном списке (достаточно DTO!), Некоторого изменения свойства, сигнала из другого места (передаваемого как наблюдаемый) и т. Д.

Вы хотите отобразить количество объектов с флагом? Один лайнер.

Вы хотите легко отображать динамические группы, основанные на свойствах, выбранных пользователем? Один лайнер.

Вы хотите сделать пейджинг? 3 строки: P

Кроме того, существует инфраструктура MVVM под названием ReactiveUI - она ​​предоставляет вам ReactiveCommand и еще несколько хитростей.

Среди них - связывающая среда с преобразователями на основе лямбд, способность реагировать в представлении на что-то очень специфическое, что произошло в вашей виртуальной машине, управление активацией моделей представления (например, начальное выполнение команды, но не в конструкторе).

Вы хотите, чтобы кнопка входа в систему была включена только в том случае, если имя пользователя и пароль не пусты?

Login = ReactiveCommand.CreateFromTask(async () => { /* your async implementation, it can return a value! */}, 
             this.WhenAnyValue(x => x.Username, x => x.Password, (user, psw) => !string.IsNullOrEmpty(user) && !string.IsNullOrEmpty(psw)); // define when the command can execute by providing IObservable<bool>

    Login.Where(x => x == true) // only successful logins, ==true for clarity 
        .InvokeCommand(DisplayMainScreen); // or something

В поле зрения вы можете сделать:

Login.Where(x => !x).Subscribe(_ =>{ // if login failed, set focus on password and select all text so user can just retype the password
          PasswordBox.SelectAllText(); // can't remember exact methods, but you get the idea
          PasswordBox.SetFocus();
       });

Для вас становится вполне естественным создавать такие функции, как «Когда что-то, сделайте это»

0 голосов
/ 02 июня 2013

Приложение CRUD будет иметь какую-то функцию поиска.Вы можете реализовать поиск в текстовом поле с помощью «type and wait to search», как в моей демонстрации, которую я недавно написал в своем блоге:

http://blog.andrei.rinea.ro/2013/06/01/bing-it-on-reactive-extensions-story-code-and-slides/

По сути, используя Throttle и другие Reactive Extensions, которые выможет создать функцию быстрого поиска.

0 голосов
/ 22 сентября 2011

Может быть, я ошибаюсь, рассмотрим два ответа.MS имеет тенденцию делить свою деятельность на многие уровни, потому что здесь у них есть интерес.

CRUD - это физическая реализация - Создать - Читать - ... Но пользовательский интерфейс кажется логичным - в контексте - дляuser ...

Иногда вам нужен слой - бизнес-слой - который контролирует поток в RDMS и обратно.По моему мнению, это очень сложно.

В финансовом бизнесе действие «обновить» или «удалить» - это репликация текущей строки с новой отметкой времени.Это затрудняет чистую операцию - по крайней мере, физическую ... И вдобавок ко всему этому вы могли бы подумать, что CRUD - это только часть транзакции - делая "логическую единицу работы" в полете, пока все не будет в порядкетогда вы должны сделать COMMIT.

Надеюсь, это поможет ...

0 голосов
/ 22 сентября 2011

Типичное приложение CRUD имеет некоторый пользовательский интерфейс (winform, WPF и т. Д.) И хранилище данных для извлечения данных и отображения в пользовательском интерфейсе.Поток данных между этими двумя компонентами (пользовательский интерфейс и хранилище данных) может быть смоделирован с использованием Rx.

Используя Rx, мы можем соединить 2 компонента (пользовательский интерфейс и хранилище данных), таких как: пользовательский интерфейс может предоставить 3 наблюдаемых для Create,Обновить и удалить (например: которые передаются в конструкторе в хранилище данных).Например: событие кнопки «Отправить» может быть отображено для создания «Создать наблюдаемые значения», а также для «Обновления и удаления».Таким образом, в основном хранилище данных должно подписаться на эти 3 наблюдаемых и не должно беспокоиться о том, как генерируются данные (это также поможет в UT, так как вы можете легко создавать поддельные наблюдаемые).

Чтение будетпростой метод чтения в хранилище данных, так как он предназначен для извлечения данных по требованию.

Таким образом, в основном Rx работал как абстракция для составления двух компонентов.

0 голосов
/ 22 сентября 2011

если вы делаете статический CRUD (получите окно / диалог с созданием, чтением, обновлением, записью и т. Д.), То, я думаю, это может помочь вам только в вашем интерфейсеНапример, может быть, вы хотите какое-то автозаполнение определенных входов.Или вы должны запросить сервис для дополнительной информации, чтобы показать.Тогда RX может помочь вам сделать это.Он скроет многие асинхронные трудности и даст читабельные, описательные выражения, которые вы легко можете прочитать и быстро сделать.В этом смысле это то же самое, что и LINQ, только для пользовательского интерфейса / async

.
...