¿Es posible transformar / validar el valor de un ISubject<T> ?
Por ejemplo, tengo un BehaviorSubject<double> zoomFactor = new(1); que me gustaría estar sujeto entre 0.1 y 10 .
zoomFactor.OnNext(Math.Clamp(newZoomFactor, 0.1, 10)) , pero hacerlo pone la responsabilidad en la persona que llama, lo cual deseo evitar.zoomFactor.Select(newZoomFactor => Math.Clamp(newZoomFactor, 0.1, 10)) , pero:zoomFactor no se cambiaría aquí: imagine que el usuario se aleja más allá del límite y vuelve a acercar, pero el zoom renderizado se mantiene en 10 durante el tiempo que el valor real vuelve silenciosamente a los límites fijados internamente...¿Qué tal crear una ISubject<T> personalizada con el comportamiento deseable?
class BehaviorTransformSubject<T> : ISubject<T> { private readonly BehaviorSubject<T> _subject; private readonly Func<T, T> _transform; public BehaviorTransformSubject(T value, Func<T, T> transform) { _subject = new BehaviorSubject<T>(value); _transform = transform; } public void OnNext(T value) => _subject.OnNext(_transform(value)); public void OnCompleted() => _subject.OnCompleted(); public void OnError(Exception error) => _subject.OnError(error); public IDisposable Subscribe(IObserver<T> o) => _subject.Subscribe(o); }Ejemplo de uso:
ISubject<double> zoomFactor = new BehaviorTransformSubject<double>(1.0, x => Math.Clamp(x, 0.1, 10.0)); Implementación alternativa: el método OnNext podría implementarse alternativamente así:
public void OnNext(T value) { T newValue; try { newValue = _transform(value); } catch (Exception ex) { _subject.OnError(ex); return; } _subject.OnNext(newValue); } Este maneja de manera diferente una posible falla de la función de transform . En lugar de devolver el error directamente al productor que invocó el método OnNext , lo propaga a los consumidores del sujeto, provocando su terminación irreversible (no se propagarán más valores a través de este sujeto). Supongo que la implementación original OnNext tiene la semántica que está buscando, pero podría estar equivocado.
Para ser justos, el método Math.Clamp nunca falla (según los documentos), por lo que esta distinción es principalmente académica en su caso.