我把代码放在Quartz上 http://fssnip.net/ec
进入VS 2013中的F#源文件。但我将最后一行放入函数中:
let start():unit=
scheduler.ScheduleJob(job, trigger) |> ignore
从脚本或主方法调用start()时,它可以正常工作。
但是当我改变了
type Job () =
interface IJob with
member x.Execute(context: IJobExecutionContext) =
Console.WriteLine(DateTime.Now)
到
// omit the (), so that Job is an interface
type Job =
interface IJob with
member x.Execute(context: IJobExecutionContext) =
Console.WriteLine(DateTime.Now)
调用start()仍然有效(即每秒打印一次),并且从main方法调用start()不再有效。 我希望无论从脚本或源文件中调用它,调用start()都将不再有效。
如果有人能解释为什么从脚本文件中调用start()仍然有效,我将不胜感激。
盛
答案 0 :(得分:2)
当省略类型行中的()时,作业类型不再具有主构造函数。它仍然是一个类,它仍然实现了IJob,但是代码中没有定义构造函数 - 在这种情况下C#会添加一个默认的无参数,F#不会。省略它不会以任何方式使Job成为一个接口 - 我想您可能想要这样做(使用对象表达式来定义接口的具体实例):
let job =
{ new IJob with
member this.Execute ...
}
现在,我不知道Quartz在安排作业时所做的细节,但很可能它会尝试创建类的实例以调用接口方法 - 因为构造函数已经消失,那个尝试失败了(我很惊讶它虽然无声地失败了。)
这是您在使用main方法调用时所看到的。
但是,当从FSI执行相同操作时,类似Job类型的类型将使用默认的无参数构造函数进行编译。我不知道为什么这两种环境之间的差异,以及它是故意的还是一个bug(我假设后者)。
您可以在类型上调用typeof<Job>.GetConstructors()
(来自System.Reflection
)进行验证。主要和FSI的结果会有所不同。