У меня есть много модулей, которые при запуске программы должны добавлять определенные вещи в один словарь, найденный в модуле более высокого уровня. Однако, похоже, что выражения и константы в модуле упаковываются в статические конструкторы при компиляции в консольное приложение, поэтому они не оцениваются, если нет явной ссылки / когда программа считает, что они необходимы.
Здесь возникло несколько вопросов, касающихся инициализации модулей, и был достигнут консенсус в отношении того, что его невозможно форсировать. Тем не менее, я не видел, чтобы кто-нибудь из них исследовал рефлексию в этом отношении. В 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: ссылка на объект не установлена для экземпляра объекта.
Я также пытался поменять конечную лямбда-функцию с помощью:
(fun typ -> try System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typ.TypeHandle) |> ignore with | ex -> printfn "%A" ex)
Но это, похоже, ничего не делает. Можно ли этого добиться?