基本上,我要做的是拥有一个通用的模拟器接口,它充当模型和用户界面之间的失去耦合,用作视图。我的模拟器界面如下所示:
type ISimulator<'Collection, 'Item, 'Value> =
inherit System.IObservable<'Collection>
inherit System.IObservable<ISimulator<'Collection, 'Item, 'Value>>
abstract Start: unit -> unit
abstract Stop: unit -> unit
abstract Reset: unit -> unit
abstract Reset: 'Collection -> unit
abstract Advance: int<gen> -> unit
abstract InitialState: 'Collection
with get
abstract CurrentState: 'Collection
with get
abstract Rule: ('Item -> 'Value)
with get, set
abstract Generation: int<gen>
with get, set
abstract Speed: float<gen/sec>
with get, set
abstract Running: bool
with get
'集合是数据集合的类型,'项是单个数据项的类型,'值是其实际值的类型(例如&lt; Matrix,Cell,float&gt;,&lt; Tree,节点,字符串&gt;等)。现在,行
inherit System.IObservable<ISimulator<'Collection, 'Item, 'Value>>
产生错误:
This type implements or inherits the same interface at different generic instantiations 'System.IObservable<Interface.ISimulator<'Collection,'Item,'Value>>' and 'System.IObservable<'Collection>'. This is not permitted in this version of F#.
实际上,我希望这个界面能够说明作为模拟运行的数据的Collection和可以单独观察模拟器本身。最后,我希望我的用户界面的一部分显示当前数据(例如矩阵)和显示和控制模拟器的不同部分,有一些按钮,如“运行”,“停止”,“重置”等。由于模拟器也可能通过其他方式停止,而不仅仅是单击按钮(例如,在达到某个特定状态,生成等)之后,该控件也需要来自模拟器的更新,但不需要更新数据的状态,但模拟器本身。
我不可能创建可观察的集合接口,因为该集合在模拟过程中不会被修改,而是通过应用函数进行转换,转换会产生一个新的集合,然后模拟器会存储(并通知收集者的观察者。)
我该怎么办?
答案 0 :(得分:3)
您是否考虑过通过属性公开可观察物,有点像传统事件?
type ISimulator<'Collection, 'Item, 'Value> =
abstract Items: System.IObservable<'Collection>
abstract Control: System.IObservable<ISimulator<'Collection, 'Item, 'Value>>
abstract Start: unit -> unit
...
这允许消费者明确他们正在观察的行为。
答案 1 :(得分:0)
在这里,我做了IObservable的这个简单实现,然后我根据dahlbyk提供的接口定义公开公共属性。我在this website找到了这个实现的基本思路,并从那里概括了一点:
open System
type Observable<'a>() =
let mutable _observers: List<IObserver<'a>> = []
let Notify func =
_observers
|> Seq.map(fun (observer: IObserver<'a>) -> async { return func observer} )
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
interface IObservable<'a> with
member this.Subscribe (observer: IObserver<'a>) =
_observers <- observer :: _observers
{ new IDisposable with
member this.Dispose() =
_observers <- _observers |> List.filter((<>) observer) }
member this.Next value =
Notify(fun (observer: IObserver<'a>) -> observer.OnNext value)
member this.Error error =
Notify(fun (observer: IObserver<'a>) -> observer.OnError error)
member this.Completed() =
Notify(fun (observer: IObserver<'a>) -> observer.OnCompleted)
包含此实现的实例作为属性的类只将其视为Observable<'a>
对象,而对于其他所有对象,它仅作为IObservable<'a>
接口公开。我认为这在松散耦合方面很好,并且仍允许在Observer / Observable对的任一端非常简单地使用。
P.S。:这也是我喜欢F#的原因 - 这个整个结构在用C ++这样的语言实现时会非常麻烦;但是在这里我可以将一个函数传递给另一个函数,以便将它应用于所有观察者。 :)