Mariano Ravinale's Blog

Sharing Experiences

Reactive Extensions en Silverlight(RX)

leave a comment »

Si bien, la idea inicial era ir haciendo los post de forma incremental y que evolucione desde los patrones de diseño, hacia patrones mas avanzados como mvc, mvp hasta llegar a mvvm y empezar con Silverlight,  crei que es importante hablar de Rx ya que nos ayudara enormemente en Silverlight, y como estamos en el browser desde el lado cliente, seguramente habra muchas llamadas asyncronicas, es ahi donde Rx entra en juego.

podriamos definir a Rx(Reactive extensions) como una libreria para aplicaciones que necesiten hacer llamadas asincronicas y orientadas a eventos utilizando colecciones del tipo Observable.

En la pagina principal explica un poco el significado de esta nueva herramienta, que nos ayudará mucho a controlar y orquestar programaticamente estos eventos y llamadas.

Pagina principal, introduccion y Video Chanel 9.

http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

Ejemplos:

http://rxwiki.wikidot.com/101samples

Bien si se fijan en la pagina principal dice:

“Rx is a superset of the standard LINQ sequence operators that exposes asynchronous and event-based computations as push-based, observable collections via the new .NET 4.0 interfaces IObservable<T> and IObserver<T>.  These are the mathematical dual of the familiar IEnumerable<T> and IEnumerator<T> interfaces for pull-based, enumerable collections in the .NET Framework.”

Creo que este parrafo explica rapidamente de que se trata Rx. A mi entender lo que trata de expresar es que Rx es un conjunto de operaciones que utiliza los eventos a los que se suscribe como punto de entrada para llenar collecciones del tipo observable para que de esta manera nos avise cuando podemos empezar a consumir los datos como si estos estuvieran en una collecion o dispare el consumo de estos de forma automatica.

Pero volviendo a Silverlight podemos encontrarle gran utilidad si utilizamos el patron mvvm, ya que tenemos un binding entre la vista y el ViewModel por lo tanto nos ayudara a simplificar y automatizar el proceso de llamado al  servidor en busqueda de datos, por ejemplo, que es mas o menos lo que esta en el codigo de abajo.

En este caso lo que hice es crear una clase con patron Singleton como Clase y utilizarla como Modelo , para poderla reutilizar, y una llamada a un servicio para poder obtener datos,  en este caso,consumiremos los nombres de unas personas.


public class ServicePeopleModel{

        private static volatile ServicePeopleModel instance;
        private static object keyLock = new Object();

        public static ServicePeopleModel CurrentInstance {
            get {
                if (instance == null) {
                    lock (keyLock) {
                        instance = new ServicePeopleModel();
                    }
                }
                return instance;
            }
        }

        /// <summary>
        /// Gets the remote people data.
        /// </summary>
        /// <returns></returns>
        public IObservable<Person> GetPeople() {

            SLPeopleServiceClient client = new SLPeopleServiceClient();

            var observable =
            
             //first we are going to listen the event, 
             //when is ready to fill our collection
             (from response in Observable.FromEvent
             <GetPeopleCompletedEventArgs>(client, "GetPeopleCompleted")
            
            //when the data arrives and the collection is ready,
            //I need to transform this data.
             from people in ConvertItems
             (response.EventArgs.Result.ToList<String>()).ToObservable()
            
            //and when it is ready return observable
            //collection, -and stay tuned
            //when all the operations
            //are done, because i'm gonna call you, 
            //says the observable collection.
            select people).ObserveOnDispatcher();
            
            //let's call the service
            client.GetPeopleAsync();

            return observable;

        }

        /// <summary>
        /// Converts the items.
        /// </summary>
        public IEnumerable<Person> ConvertItems(List<String> response){
            var people = new List<Person>();
            response.ForEach(person => people.Add(
                new Person() {Name = person})
            );
            return people;
        }

    }
public class Person {

    public string Name { get; set; }

}

Ok, ya hemos visto como hariamos nuestro modelo para pedir los datos a nuestro servicio, transformar los datosy devolver una coleccion con todos los datos, listos para utilizar.
Pero nos falta bindear estos datos contra la vista, para automatizar la tarea, de forma que cuando vengan los datos la vista lo muestre estos datos sin que tengamos que intervenir.

//On The PeopleViewModel

public class PeopleViewModel: ViewModelBase {

    /// <summary>
    /// Initializes a new instance of the PeopleViewModelclass.
    /// </summary>
    public PeopleViewModel() {
         
        var client = Observable.Empty<Person>();
                       
        //we've suscribed to a changed event and we 
        //want to select the first person to show it on the view
        PeopleCollection.CollectionChanged += (s, e) => {
           SelectedPersonProperty = PeopleCollection[0].Name;
        };

        //let's the magic starts
        client = ServicePeopleModel.CurrentInstance.GetPeople();

        //and suscribe us to the service result
        client.Subscribe((item) => {
           PeopleCollection.Add(item);
        });
    }

     /// <summary>
     /// Gets or sets SelectedPersonProperty 
     /// </summary>
     public string SelectedPersonProperty {
         get {
             return _selectedPersonProperty ;
         }
         set {
             if (_selectedPersonProperty == value) return;
                 _selectedPersonProperty = value;
             RaisePropertyChanged("SelectedPersonProperty ");
         }
     }
     
       /// <summary>
        /// Gets or sets the PeopleCollection.
        /// </summary>
        /// <value>PeopleCollection.</value>
        public ObservableCollection<Person> PeopleCollection{
            get {
                if(_popleCollection == null){
                    _peopleCollection = new ObservableCollection<Person>();
                }
                return _peopleCollection;
            }
            set {
                if (_peopleCollection == value) return;
                _peopleCollection= value;
                RaisePropertyChanged("PeopleCollection");
            }
        }
}

Sin embargo si ven la pagina de ejemplos podran ver mushisimas mas aplicaciones de este framework, que a mi parecer es excelente tratando de unir el observer pattern y el Iterator, de forma sencilla y con altos beneficios en cantidad y calidad de codigo.

tengo otra aplicacion parecida hecha con Rx que posteare mas adelante, creo que vale la pena bajarselo y probarlo e irle toamndo la mano, creo que despues se va volviendo natural y uno le comienza a ver mas aplicaciones.

Dejo algunos links:

http://www.silverlightshow.net/items/Using-Reactive-Extensions-in-Silverlight.aspx

http://blogs.msdn.com/b/somasegar/archive/2009/11/18/reactive-extensions-for-net-rx.aspx

Para los amantes y expertos javascript (@cortezcristian) 😉

http://codebetter.com/blogs/matthew.podwysocki/archive/2010/02/16/introduction-to-the-reactive-extensions-to-javascript.aspx





Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.

Anuncios

Written by @mravinale

agosto 16, 2010 a 4:45 am

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: