【问题标题】:Using reactive extensions for a simulation engine为模拟引擎使用响应式扩展
【发布时间】:2012-04-17 19:01:57
【问题描述】:

您将如何使用响应式扩展构建一个简单的模拟引擎?例如,假设您有一个类Motor,其属性为IsPoweredSpeed。您希望通过让 Speed 从 0 到 1000 RPM 以每秒 10 RPM 的速度上升 100 秒来对 IsPowered 从 false 变为 true 做出反应。

稍微抽象一下,假设您想提供一个可插入的 API,其中类及其属性事先不知道。相反,模拟引擎会获得可观察的属性变化流,通过创建额外的属性变化来做出反应,其中许多变化是利用 Rx 随时间递增发生的。这样的 API 可能是什么样的?

【问题讨论】:

  • 您希望引擎轮询属性的更改,还是模型会公开事件或可观察对象以通知更改?
  • 模型将公开属性(例如IsPowered)已更改的事件或可观察对象。 (至于哪个事件或可观察的更好,这是我正在寻找的指导的一部分。)
  • 那么,在您的示例中,Motor 类将具有 IsPoweredObservableSpeedObservable 属性(或等效事件)以及 IsPoweredSpeed 属性?
  • 是的,按照这些思路。对于使用属性更改,我认为您会根据IObservable/IObserver Development Model 公开IObserver 而不是IObservable。将两者结合起来并抽象出属性,像 Subject<PropertyChange> 这样的东西会起作用吗?
  • 不要暴露观察者 - 任何杂散的代码都可以调用 OnCompletedOnError 并将您的应用程序变成糊状。对象也是观察者,所以也不要暴露它们。

标签: simulation system.reactive


【解决方案1】:

模拟 API 需要一个表示属性更改的类型和一个具有传入和传出 IObservable<T> 更改流的模拟方法。模拟引擎的实现将包含对传入属性更改做出反应以更新输出流的规则。

类型应该是这样的(虽然结构可能比类更好):

class PropertyChange
{
    public PropertyChange(string name, object value) { Name = name; Value = value; }
    public string Name { get; private set; }
    public object Value { get; private set; }
}

模拟方法如下所示。为了演示多个规则,此代码预设了一个属性 IsLightOn,它只跟踪 IsPowered

IObservable<PropertyChange> Simulate(IObservable<PropertyChange> incomingChanges)
{
    var isLightOnRule =
        from c in incomingChanges
        where c.Name == "IsPowered"
        select new PropertyChange("IsLightOn", c.Value);

    var ramp = Observable.Generate(0, speed => (speed <= 1000), speed => speed + 10, speed => new PropertyChange("Speed", speed), _ => TimeSpan.FromSeconds(1));
    var speedRule = incomingChanges
        .Where(c => c.Name == "IsPowered" && (bool)c.Value)
        .SelectMany(ramp);

    // Add more rules here.

    return Observable.Merge(isLightOnRule, speedRule /* merge more rules here */);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 2014-07-31
    • 2012-01-06
    • 2014-05-17
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    相关资源
    最近更新 更多