IObservable.Subscribe导致System.Delegate.CreateDelegate引发Argum



我希望将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事件之一并获得IOobservable。。。

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.rnParameter 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:UsersBarend VenterDocumentsVisual Studio 2008ProjectsSdlDemoSdlDemoTutorial.fs:line 77
  InnerException: 

我完全被难住了。为什么会发生这种情况?我需要在哪里做一些eta扩展吗?

经过一些修改,我能够将运行时异常变成一个方便的类型错误。似乎将观察者的类型从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))

也许很不幸的是,我在这里发帖后这么快就找到了一个困扰了我好几天的解决方案。希望它对某些人有用。

与其创建自己的包装函数来将F#适配为Rx,为什么不直接使用标准F#Control.Observable模块中的函数呢?

这可能无法解决您的其余问题,但您是否注意到IEvent继承了IOobservable?您的fromEvent函数可以实现为一个简单的强制转换。。。

let fromEvent (e: IEvent<'H,'T>) = e :> IObservable<'T>

相关内容

  • 没有找到相关文章

最新更新