2017-07-17 35 views
7

uzun reaktif zincirlerinin oluşturulması saklanması Nasıl Şu anda var Rx/ReactiveUI aşağıdaki kod bloğu: Gördüğünüz gibigözlenebilirlerin

 this.WhenAnyValue(x => x.Listras) 
      .Where(item => item != null) 
      .Throttle(TimeSpan.FromMilliseconds(millis)) 
      .ObserveOn(TaskPoolScheduler.Default) 
      .Select(im => GetArray.FromChannels(im, 0, 1)) 
      .ObserveOn(RxApp.MainThreadScheduler) 
      .ToProperty(this, x => x.Grayscale, out _grayscale); 

     this.WhenAnyValue(x => x.Grayscale) 
      .Where(item => item != null) 
      .Throttle(TimeSpan.FromMilliseconds(millis)) 
      .ObserveOn(TaskPoolScheduler.Default) 
      .Select(ar => Gaussian.GaussianConvolution(ar, 1.5)) 
      .ObserveOn(RxApp.MainThreadScheduler) 
      .ToProperty(this, x => x.BlurMenor, out _blurMenor); 

     this.WhenAnyValue(x => x.BlurMenor) 
      .Where(item => item != null) 
      .Throttle(TimeSpan.FromMilliseconds(millis)) 
      .ObserveOn(TaskPoolScheduler.Default) 
      .Select(ar => { ConversorImagem.Converter(ar, out BitmapSource im); return im; }) 
      .ObserveOn(RxApp.MainThreadScheduler) 
      .ToProperty(this, x => x.ImagemBlurMenor, out _imagemBlurMenor); 

     this.WhenAnyValue(x => x.BlurMenor) 
      .Where(item => item != null) 
      .Throttle(TimeSpan.FromMilliseconds(millis)) 
      .ObserveOn(TaskPoolScheduler.Default) 
      .Select(ar => Gaussian.VerticalGaussianConvolution(ar, 5)) 
      .ObserveOn(RxApp.MainThreadScheduler) 
      .ToProperty(this, x => x.BlurMaior, out _blurMaior); 

     this.WhenAnyValue(x => x.BlurMaior) 
      .Where(item => item != null) 
      .Throttle(TimeSpan.FromMilliseconds(millis)) 
      .ObserveOn(TaskPoolScheduler.Default) 
      .Select(ar => { ConversorImagem.Converter(ar, out BitmapSource im); return im; }) 
      .ObserveOn(RxApp.MainThreadScheduler) 
      .ToProperty(this, x => x.ImagemBlurMaior, out _imagemBlurMaior); 

     this.WhenAnyValue(x => x.BlurMenor, x => x.BlurMaior) 
      .Where(tuple => tuple.Item1 != null && tuple.Item2 != null) 
      .Throttle(TimeSpan.FromMilliseconds(millis)) 
      .ObserveOn(TaskPoolScheduler.Default) 
      .Select(tuple => ArrayOperations.Diferença(tuple.Item1, tuple.Item2)) 
      .ObserveOn(RxApp.MainThreadScheduler) 
      .ToProperty(this, x => x.Diferença, out _diferença); 

     this.WhenAnyValue(x => x.Diferença) 
      .Where(item => item != null) 
      .Throttle(TimeSpan.FromMilliseconds(millis)) 
      .ObserveOn(TaskPoolScheduler.Default) 
      .Select(ar => { ConversorImagem.Converter(ar, out BitmapSource im); return im; }) 
      .ObserveOn(RxApp.MainThreadScheduler) 
      .ToProperty(this, x => x.ImagemDiferença, out _imagemDiferença); 

, bu flagrantly KURU ilkesine aykırı, ama nasıl bilmiyorum Özelliklerin ve delegelerin geçişini değiştirebilirdim.

Rx/ReactiveUI'de bu yöntem zincirlerinin oluşturulmasını otomatikleştirmenin genel yolu nedir?

cevap

8

Rx'in güzelliği, diğer operatörlere bağlı olarak kendi operatörlerinizi oluşturabilmenizdir. Bunun nedeni Rx'in fonksiyonel tarafıdır.

// Put this class somewhere useful. Either beside your VM inside the same namespace 
// Or in a seperate file for all your custom operators 
public static class ObservableMixins 
{ 
    public static IObservable<TOut> ThrottledSelect<TIn, TOut>(this IObservable<TIn> source, int milliseconds, Func<TIn, TOut> selector) => 
     source 
      .Where(item => item != null) 
      .Throttle(TimeSpan.FromMilliseconds(milliseconds)) 
      .ObserveOn(TaskPoolScheduler.Default) 
      .Select(selector) 
      .ObserveOn(RxApp.MainThreadScheduler) 
} 

böyle kullanılması it:

yaygın olarak kullanılan tüm davranışlarını kapsüller ve parametre olarak küçük farklılıklar götüren yeni operatörünü oluşturabilir Eğer bir hissediyorsanız

this.WhenAnyValue(x => x.Listras) 
    .ThrottledSelect(millis, im => GetArray.FromChannels(im, 0, 1)) 
    .ToProperty(this, x => x.Grayscale, out _grayscale); 

this.WhenAnyValue(x => x.Grayscale) 
    .ThrottledSelect(millis, ar => Gaussian.GaussianConvolution(ar, 1.5)) 
    .ToProperty(this, x => x.BlurMenor, out _blurMenor); 

this.WhenAnyValue(x => x.BlurMenor) 
    .ThrottledSelect(millis, ar => { ConversorImagem.Converter(ar, out BitmapSource im); return im; }) 
    .ToProperty(this, x => x.ImagemBlurMenor, out _imagemBlurMenor); 

this.WhenAnyValue(x => x.BlurMenor) 
    .ThrottledSelect(millis, ar => Gaussian.VerticalGaussianConvolution(ar, 5)) 
    .ToProperty(this, x => x.BlurMaior, out _blurMaior); 

this.WhenAnyValue(x => x.BlurMaior) 
    .ThrottledSelect(millis, ar => { ConversorImagem.Converter(ar, out BitmapSource im); return im; }) 
    .ToProperty(this, x => x.ImagemBlurMaior, out _imagemBlurMaior); 

this.WhenAnyValue(x => x.BlurMenor, x => x.BlurMaior) 
    // Notice how I'm returning a null if either item is null 
    // It will be filtered in the operator 
    .Select(tuple => tuple.Item1 != null || tuple.Item2 != null ? null : tuple) 
    .ThrottledSelect(millis, tuple => ArrayOperations.Diferença(tuple.Item1, tuple.Item2)) 
    .ToProperty(this, x => x.Diferença, out _diferença); 

this.WhenAnyValue(x => x.Diferença) 
    .ThrottledSelect(millis, ar => { ConversorImagem.Converter(ar, out BitmapSource im); return im; }) 
    .ToProperty(this, x => x.ImagemDiferença, out _imagemDiferença); 

biraz daha az maceracı, elbette onu gözlemlenebilir bir yöntem olarak kullanabilirsiniz normal bir yöntem olarak kullanabilirsiniz:

public IObservable<T> ThrottledSelect<TIn, TOut>(IObservable<TIn> source, int milliseconds, Func<TIn, TOut> selector) => 
    source 
     .Where(item => item != null) 
     .Throttle(TimeSpan.FromMilliseconds(milliseconds)) 
     .ObserveOn(TaskPoolScheduler.Default) 
     .Select(selector) 
     .ObserveOn(RxApp.MainThreadScheduler) 

Ve bunun gibi kullanın:

ThrottledSelect(this.WhenAnyValue(x => x.Diferença), millis, ar => { ConversorImagem.Converter(ar, out BitmapSource im); return im; }) 
    .ToProperty(this, x => x.ImagemDiferença, out _imagemDiferença);