c# - 限制 BehaviorSubject 的值
问题描述
是否可以转换/验证a 的值ISubject<T>
?
例如,我有一个BehaviorSubject<double> zoomFactor = new(1);
我想被夹在0.1
和之间10
。
- 应该可以调用
zoomFactor.OnNext(Math.Clamp(newZoomFactor, 0.1, 10))
,但是这样做会将责任放在调用者身上,我希望避免这种情况。 - 我可以使用 观察进行转换
zoomFactor.Select(newZoomFactor => Math.Clamp(newZoomFactor, 0.1, 10))
,但是:- 这是再次将责任外包给另一个调用者;
- 原始
zoomFactor
值不会在这里改变:想象用户缩小超过限制,然后放大,但在10
实际值默默地回到内部钳制边界期间,渲染的缩放被卡住了......
解决方案
如何创建ISubject<T>
具有理想行为的自定义实现?
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);
}
使用示例:
ISubject<double> zoomFactor = new BehaviorTransformSubject<double>(1.0,
x => Math.Clamp(x, 0.1, 10.0));
替代实现:该OnNext
方法可以像这样替代实现:
public void OnNext(T value)
{
T newValue;
try { newValue = _transform(value); }
catch (Exception ex) { _subject.OnError(ex); return; }
_subject.OnNext(newValue);
}
这个处理不同的transform
功能可能失败。它没有将错误直接扔回调用该OnNext
方法的生产者,而是将其传播给主体的消费者,导致其不可逆转的终止(不再通过该主体传播值)。我猜原始OnNext
实现具有您正在寻找的语义,但我可能错了。
公平地说,该Math.Clamp
方法永远不会失败(根据文档),因此在您的情况下,这种区别主要是学术性的。
推荐阅读
- python-3.x - TypeError:在现有工作簿工作表上写入时“工作表”对象不可调用
- function - 如何在函数内打印输入变量的结果
- shopify - 在 Shopify 的 Liquid 中格式化电话号码
- xcode - Xcode 12.4“您无权保存文件...”在 CATALINA 上运行
- javascript - 从我的命令行 Telnet 登录和密码失败
- typescript - WebPack 的任务运行程序找不到任何模块
- excel - Excel VBA条件格式自定义公式
- java - 无法在项目 someProject 上执行目标 org.springframework.boot:spring-boot-maven-plugin:1.4.2.RELEASE:run (default-cli):无法执行 java
- box-api - BoxV2 .Net API RefreshAccessTokenAsync() 方法抛出对象引用错误
- c++ - 验证数组用户输入c ++