我希望将cs-sdl挂钩到Rx。我已经让它在C#中工作,但在F#中,一些相当奇怪的东西开始发生。我想坚持使用F#,这样我就可以节省一些编程时间并将SDL事件作为参数传递给整齐地将它们包装在IObservables中。我试图这样做:
let fromEvent (e: IEvent<'H,'T>) = Observable.FromEventPattern<'H,'T>((fun h -> e.AddHandler(h)),(fun h -> e.RemoveHandler(h)))
到目前为止一切顺利。现在传递一个SDL事件并获得一个IObservable ......
let MouseMotion = fromEvent(Events.MouseMotion)
依此类推这套模块。所有推断类型都是正确的。 MouseMotion的类型为IObservable<MouseMotionEventArgs>
现在我在这里实际使用这个库来测试它的另一个项目:
let observer : IObserver<MouseMotionEventArgs> = Observer.Create(Action<MouseMotionEventArgs>(fun x -> System.Console.WriteLine(x.X.ToString())))
ignore <| SdlDotNet.Reactive.CoreInput.MouseMotion.Subscribe(Observer.AsObserver(observer))
以下是我运行时会发生的事情:
System.ArgumentException was unhandled
Message="Type must derive from Delegate.\r\nParameter name: type"
Source="mscorlib"
ParamName="type"
StackTrace:
at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method)
at System.Reactive.Linq.Observable.<>c__DisplayClass19d`2.<FromEvent>b__19b(IObserver`1 observer)
at System.Reactive.AnonymousObservable`1.<>c__DisplayClass1.<Subscribe>b__0()
at System.Reactive.Concurrency.Scheduler.Invoke(IScheduler scheduler, Action action)
at System.Reactive.Concurrency.ScheduledItem`2.InvokeCore()
at System.Reactive.Concurrency.ScheduledItem`1.Invoke()
at System.Reactive.Concurrency.CurrentThreadScheduler.Trampoline.Run()
at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[TState](TState state, TimeSpan dueTime, Func`3 action)
at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[TState](TState state, Func`3 action)
at System.Reactive.Concurrency.Scheduler.Schedule(IScheduler scheduler, Action action)
at System.Reactive.AnonymousObservable`1.Subscribe(IObserver`1 observer)
at <StartupCode$SdlDemo>.$Tutorial.main@() in C:\Users\Barend Venter\Documents\Visual Studio 2008\Projects\SdlDemo\SdlDemo\Tutorial.fs:line 77
InnerException:
我完全难过了。为什么会这样?我需要在某处进行一些eta扩展吗?
答案 0 :(得分:1)
经过一番摆弄,我能够将运行时异常变成一个方便的类型错误。似乎将观察者的类型从IObserver<MouseMotionEventArgs>
更改为IObserver<EventPattern<MouseMotionEventArgs>>
就可以了:
let observer = Observer.Create(fun (x : EventPattern<MouseMotionEventArgs>) -> System.Console.WriteLine(x.EventArgs.X.ToString()))
ignore <| SdlDotNet.Reactive.CoreInput.MouseMotion.Subscribe((observer))
或许不幸的是,在我发布这里之后很快就会找到一个让我好几天的解决方案。希望它对某人有用。
答案 1 :(得分:1)
为什么不使用标准F#Control.Observable
模块中的函数,而不是创建自己的包装函数来使F#适应Rx?
答案 2 :(得分:1)
这可能无法解决您的其他问题,但您是否注意到IEvent inherits from IObservable?您的fromEvent
函数可以实现为简单的演员......
let fromEvent (e: IEvent<'H,'T>) = e :> IObservable<'T>