用反射评估模块的静态构造函数

时间:2019-03-14 19:44:27

标签: f# system.reflection static-constructor

我有很多模块,在启动程序时应该向某些在更高级别模块中找到的Dictionary添加某些内容。但是,似乎将模块中的表达式和常量编译到Console App时会打包到静态构造函数中,因此,除非明确引用/在程序认为需要它们时,否则不会对它们进行求值。

这里有一些关于初始化模块的问题,人们一致认为不可能强制执行。但是,我还没有看到他们中的任何一个对此进行反思。在C#中,我知道您可以调用类型的静态构造函数,因此我尝试对F#模块进行同样的操作。

我的尝试涉及到向每个模块添加一个自定义属性(MessageHandlerAttribute),该模块包含一个我希望在启动程序时求值的表达式,然后运行以下命令:

let initAllMessageHandlerModules =
    Assembly.GetExecutingAssembly().GetTypes() 
    |> Array.choose (fun typ -> 
        typ.CustomAttributes 
        |> Seq.tryFind (fun attr -> attr.AttributeType = typeof<MessageHandlerAttribute>)
        |> Option.map (fun _ -> typ))
    |> Array.iter 
        (fun typ -> try typ.TypeInitializer.Invoke(null, null) |> ignore with | ex -> printfn "%A" ex)

但这给了我以下错误: System.NullReferenceException:对象引用未设置为对象的实例。

我还试图与此交换最终的lambda函数:

(fun typ -> try System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typ.TypeHandle) |> ignore with | ex -> printfn "%A" ex)

但这似乎无济于事。有可能做到这一点吗?

1 个答案:

答案 0 :(得分:0)

使用type.GetConstructor而不是type.TypeInitializer。

[dateRange]

Here是另外一些示例