用反射评估模块的静态构造函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用反射评估模块的静态构造函数相关的知识,希望对你有一定的参考价值。
我有很多模块,在启动程序时,应该将某些内容添加到更高级别模块中的单个词典中。但是,在编译到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)
但这似乎什么都不做。是否有可能实现这一目标?
答案
使用type.GetConstructor而不是type.TypeInitializer。
(fun typ -> try typ.GetConstructor(BindingFlags.Instance ||| BindingFlags.Public, null, CallingConventions.Standard, Array.empty<Type>, Array.empty<ParameterModifier>).Invoke(null, null) |> ignore with | ex -> printfn "%A" ex)
Here是更多的例子
以上是关于用反射评估模块的静态构造函数的主要内容,如果未能解决你的问题,请参考以下文章