2017-07-17 27 views
7

Hiện nay tôi có khối mã sau đây Rx/ReactiveUI:Làm thế nào để đóng gói việc tạo ra các chuỗi phản ứng dài quan sát

 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); 

Như bạn có thể thấy, nó trắng trợn vi phạm các nguyên tắc DRY, nhưng tôi không biết làm thế nào Tôi có thể parameterize đi qua các thuộc tính và đại biểu.

Cách thông thường để tự động hóa việc tạo chuỗi các phương thức này trong Rx/ReactiveUI là gì?

Trả lời

8

Vẻ đẹp của Rx là bạn có thể tạo các toán tử của riêng mình dựa trên các toán tử khác. Điều này là do bên chức năng của Rx.

Bạn có thể tạo một nhà điều hành mới mà gói gọn tất cả các hành vi phổ biến và có sự khác biệt nhỏ như các thông số:

// 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) 
} 

Việc sử dụng nó như thế này:

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); 

Nếu bạn đang cảm thấy một ít mạo hiểm hơn, bạn tất nhiên có thể sử dụng nó như một phương pháp thông thường có thể quan sát được:

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) 

Và sử dụng nó như thế này:

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); 
Các vấn đề liên quan