背景
我正在学习生成式类型提供程序。
我使用了 Cameron Taggart 的 VectorTP 示例,这里 和 这里。在那段代码中,他构建了一个 C# 代码的向量类,该类具有设计时指定的属性数量,编译它,并返回生成的类型。它工作得很好。
例如,这个客户端代码可以编译并运行:
type Vector2D = Vector<"X", "Y">
let v1 = Vector2D()
v1.X <- 3.14
v1.Y <- 2.91
如果你观察设计时类型提供程序代码内部的情况,你会发现类型提供程序代码是这样被调用的:
ITypeProvider.ApplyStaticArguments(
VectorTP.Vector, // typeWithoutArguments
[|"ConsoleApplication8"; "Vector2D"|], // typeNameWithArguments
[|"X"; "Y"; ""; ""; ""; ""; ""|]) // staticArguments
我看起来都不错。
问题
这段客户端代码无法编译:
type Vector2D = Vector<"X", "Y">
let list = System.Collections.Generic.List<Vector2D>()
这次,如果你在设计时查看类型提供程序代码的内部情况,当List<Vector2D>
被添加到客户端代码时,你会看到这个额外的调用:
ITypeProvider.ApplyStaticArguments(
Mindscape.Vectorama.Vector2D, // typeWithoutArguments
[|"Vector2D,"|], // typeNameWithArguments
[|""; ""; ""; ""; ""; ""; ""|]) // staticArguments
看起来,类型提供程序框架(是否正确的术语?)正在调用`ITypeProvider.ApplyStaticArguments`,要求基于`Vector2D`生成类型而没有任何静态参数。但是,`Vector2D`已经是生成的类型了?!
VectorTP示例没有正确处理这种情况,因此客户端代码将无法编译。
注意:
我尝试将`type Vector2D = Vector<"X", "Y">`声明移动到一个单独的DLL中,然后引用该DLL。当然,这符合预期。此时生成的`Vector2D`类看起来就像任何其他类型一样。
复杂之处似乎在于生成类型并在同一程序集(或脚本,虽然我没有尝试过)中使用它作为泛型参数。
问题:
1. 这是"type provider framework"中的问题吗?还是这是预期行为? 2. 当我使用生成的类型作为泛型类型参数时,为什么会调用`ApplyStaticArguments`? 3. 如果`ITypeProvider`应该处理这种情况,那么正确的响应是什么?