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

问题描述 投票:3回答:1

我正在创建一个项目,其中有单独的源文件/模块,它们将函数添加到更高级别文件中包含的单个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 -> ....
)
f#
1个回答
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之前,当执行代码第一次遇到给定类型时,静态类型上下文被初始化,无论用户代码是与该类型的instace还是静态成员交互。在.NET 4之后,这稍微改变了 - 只有当用户代码与该类型的静态成员交互时,才会初始化静态上下文。

© www.soinside.com 2019 - 2024. All rights reserved.