Ponte com eventos existentes do .NET
O Rx fornece métodos de fábrica para que você faça a ponte com fontes assíncronas existentes no .NET para que você possa empregar os recursos avançados de composição, filtragem e gerenciamento de recursos fornecidos pelo Rx em qualquer tipo de fluxo de dados. Este tópico examina o operador FromEventPattern que permite "importar" um evento .NET para o Rx como uma sequência observável. Sempre que um evento for gerado, uma mensagem OnNext será entregue à sequência observável. Em seguida, você pode manipular dados de evento como qualquer outra sequência observável.
O Rx não visa substituir modelos de programação assíncrona existentes, como eventos do .NET, o padrão assíncrono ou a Biblioteca de Paralelismo de Tarefas. No entanto, quando você tentar redigir eventos, os métodos de fábrica do Rx fornecerão a conveniência que não pode ser encontrada no modelo de programação atual. Isso é especialmente verdadeiro para manutenção de recursos (por exemplo, quando cancelar a assinatura) e filtragem (por exemplo, escolher que tipo de dados receber). Neste tópico e nos seguintes tópicos, você pode examinar como esses recursos Rx podem ajudá-lo na programação assíncrona.
Convertendo um evento .NET em uma sequência observável Rx
O exemplo a seguir cria um manipulador de eventos .NET simples para o evento de movimentação do mouse e imprime o local do mouse em um rótulo em um formulário do Windows.
using System.Linq;
using System.Windows.Forms;
using System.Reactive;
using System.Reactive.Linq;
using System;
using WinForm;
using System.Reactive.Disposables;
class Program {
static void Main()
{
var lbl = new Label();
var frm = new Form { Controls = { lbl } };
frm.MouseMove += (sender, args) =>
{
lbl.Text = args.Location.ToString();
};
Application.Run(frm);
};
}
Para importar um evento para o Rx, você pode usar o operador FromEventPattern e fornecer os objetos EventArgs que serão gerados pelo evento que está sendo ponteado. O operador FromEventPattern trabalha com eventos que usam um remetente de objeto e alguns EventArgs e usa reflexão para localizar esses métodos de adição/remoção para você. Em seguida, ele converte o evento fornecido em uma sequência observável com um tipo EventPattern que captura o remetente e os argumentos do evento.
Para delegados que têm um parâmetro (eventos não padrão), você pode usar o operador FromEvent, que usa um par de funções usadas para anexar e desanexar um manipulador.
No exemplo a seguir, convertemos o fluxo de eventos de movimentação do mouse de um formulário do Windows em uma sequência observável. Sempre que um evento de movimentação do mouse for acionado, o assinante receberá uma notificação OnNext. Em seguida, podemos examinar o valor EventArgs dessa notificação e obter o local da movimentação do mouse.
using System.Linq;
using System.Windows.Forms;
using System.Reactive;
using System.Reactive.Linq;
using System;
using WinForm;
using System.Reactive.Disposables;
class Program {
static void Main()
{
var lbl = new Label();
var frm = new Form { Controls = { lbl } };
IObservable<EventPattern<MouseEventArgs>> move = Observable.FromEventPattern<MouseEventArgs>(frm, "MouseMove");
move.Subscribe(evt => {
lbl.Text = evt.EventArgs.Location.ToString();
}) ;
Application.Run(frm);
};
}
Observe que, neste exemplo, move
torna-se uma sequência observável na qual podemos manipular ainda mais. O tópico Consultando sequências observáveis usando operadores LINQ mostrará como você pode projetar essa sequência em uma coleção do tipo Points e filtrar seu conteúdo, para que seu aplicativo receba apenas valores que atendam a determinados critérios.
A limpeza do manipulador de eventos é feita pelo objeto IDisposable retornado pelo método Subscribe. Chamar Dispose (feito ao chegar ao final do bloco de uso neste exemplo) liberará todos os recursos que estão sendo usados pela sequência, incluindo o manipulador de eventos subjacente. Isso essencialmente cuida da não assinatura de um evento em seu nome.