F#:获取源文件以自动评估

时间:2019-02-14 21:47:44

标签: f#

我正在制作一个项目,其中有单独的源文件/模块,这些源文件/模块将功能添加到更高级别文件中包含的单个Dictionary中。但是,我发现这些源文件中没有任何东西可以单独求值,即使是不带参数或代码的函数,甚至都不在函数内部。

因此,没有将任何内容添加到字典中。有没有办法自动强制评估模块中的完整功能调用?我将举一个我想做的事的例子:

Registry.fs:

let private functions = Dictionary<string, MessageHandler>()

let add type handler = 
    functions.Add(type, handler)

Handler1.fs:

Registry.add "type1" (fun m -> ....
)

Handler2.fs:

Registry.add "type2" (fun m -> ....
)

1 个答案:

答案 0 :(得分:3)

我相信您需要查看this relevant topic。当F#代码被编译为IL时,松散的方法调用将作为封装类型/模块的static构造函数内部的方法调用进行编译。仅看图片,这大致相当于以下C#代码:

static class Handler1 {
    static Handler1() {
        // this is the static constructor
        Registry.add "type1" .... 
    }
}

在.NET static中,构造函数未急于初始化 1 。这意味着,如果要使.NET运行时调用Handler1静态构造函数,则需要访问Handler1类型的静态成员。

在静态上下文中使用类型的示例是

  1. 公开一个易于访问的静态成员/方法:

    module Handler1 =
        [<Literal>]
        let Name = "Handler1"
    
  2. 从您的代码访问该静态成员,例如main方法:

    [<EntryPoint>]
    let main args =
        printf Handler1.Name 
    

上面的行将强制.NET运行时加载Handler1类型的静态上下文,如果该类型首次被您的代码枚举,则将导致调用静态构造函数。如果您的代码从未遇到给定类型的静态上下文(任何静态成员或方法),则它将永远不会初始化-静态构造函数将永远不会被调用。

此行为是.NET框架的设计(与选择的语言(C#,F#,VB等)无关,它们都编译为类似的IL)。关键是不要按从未实际使用过的类型分配不必要的资源。


1 在.NET 4之前,执行代码首次遇到给定类型时,将初始化静态类型上下文,而无论用户代码是与该实例的实例还是静态成员进行交互类型。在.NET 4之后,这一情况稍有变化-仅当用户代码与该类型的静态成员进行交互时,才会初始化静态上下文。