我有一个F#自定义类型提供程序(在这种情况下是CheckedRegexProvider);相关源码如下:
[<TypeProvider>]
type public CheckedRegexProvider() as this =
inherit TypeProviderForNamespaces()
// Get the assembly and namespace used to house the provided types
let thisAssembly = Assembly.GetExecutingAssembly()
let rootNamespace = "Samples.FSharp.RegexTypeProvider"
let baseTy = typeof<obj>
let staticParams = [ProvidedStaticParameter("pattern", typeof<string>)]
let regexTy = ProvidedTypeDefinition(thisAssembly, rootNamespace, "RegexTyped", Some baseTy)
do regexTy.DefineStaticParameters(
parameters=staticParams,
instantiationFunction=(fun typeName parameterValues ->
match parameterValues with ...
然后我有一个简单的测试项目,在其中将一些琐碎的代码放在 .fs 文件中。
open Samples.FSharp.RegexTypeProvider
type T = RegexTyped< @"(?<AreaCode>^\d{3})-(?<PhoneNumber>\d{3}-\d{4}$)">
我感到困惑的是,实例化函数被调用的次数比我预期的要多得多。我以为只有在更改静态参数(在这种情况下为"(?^\d{3})-(?\d{3}-\d{4}$)")时才会调用该函数,但每次我在测试源中进行操作(例如按下空格键),该lambda函数都会连续调用两次。如果我真的更改了参数,它会被调用两次或三次。
当然,这对IDE(在我的情况下是Visual Studio)有相当大的影响,特别是因为该函数旨在提供一个类型,该类型可能需要扫描某些数据源以获取模式信息。
然后我尝试将类型提供程序调用隔离在一个单独的源模块文件中(我们称之为M1.fs),并在实际测试代码(M2.fs)中打开该模块。这样,每当我触摸M1.fs时,lambda函数仍会被调用,但在我工作于M2.fs时,它根本不会被调用,这是预期的。
我的问题是:这些连续的实例化函数重新调用是否正确?这是设计如此吗?
如果是,为什么会这样?