gpt4 book ai didi

f# - 使用F#生成类型提供程序类型作为泛型类型参数

转载 作者:行者123 更新时间:2023-12-04 04:11:17 26 4
gpt4 key购买 nike

背景

我正在学习有关生成类型的提供程序。

我使用了herehere的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类看起来就像任何其他类型一样。

复杂之处似乎在于生成类型并将其用作同一程序集中的通用参数(或脚本,通过我没有尝试过)。

问题
  • 这是“类型提供程序框架”中的问题吗?还是这是预期的行为?
  • 当我将生成的类型用作泛型类型参数时,为什么要调用ApplyStaticArguments
  • 如果应该使用ITypeProvider处理这种情况,那么正确的响应是什么?
  • 最佳答案

    阅读评论并进行更多实验后,这就是我的结论。

    1.这是“类型提供程序框架”中的问题吗?还是这是预期的行为?

    这不是我所期望的行为。

    仅当您尝试将生成的类型用作泛型类型参数时,问题才变得明显。当您将生成的类型用作通用类型参数时,框架将为该生成的类型调用ITypeProvider.GetStaticParameters。我尚不清楚为什么需要这样做。

    无论如何,由于这个意外的调用,ITypeProvider.GetStaticParameters()的实现不能像下面这样简单:

    member this.GetStaticParameters(typeWithoutArguments) =
    [1..7] |> List.map (fun i -> stringParameter i "") |> List.toArray

    一定是这样的:
    member this.GetStaticParameters(typeWithoutArguments) =
    if typeWithoutArguments = typeof<Vector> then
    [1..7] |> List.map (fun i -> stringParameter i "") |> List.toArray
    else
    [||] // for the generated types like Vector2D

    完成上述更改后,我能够编译使用 List<Vector2D>的客户端代码。

    2.当我将生成的类型用作泛型类型参数时,为什么调用ApplyStaticArguments?

    注意,我最初的问题的重点是为什么要调用 ITypeProvider.ApplyStaticArguments。之所以调用 ApplyStaticArguments是因为 GetStaticParameters表示生成的类型( Vector2D)本身需要静态参数。修复 GetStaticParameters之后,不再为生成的类型调用 ApplyStaticArguments。现在,这很有意义。

    3.如果应该由ITypeProvider处理这种情况,正确的响应是什么?

    上面已经解决了。但是,它提出了一个更大的问题:“哪里有生成类型提供者的好例子?”该问题已被提出,但尚未回答 here

    最后,关于ProvidedTypes.fs

    在评论中,存在一个有关使用 ProvidedTypes.fs库是否可以解决此问题的问题。我使用 ProvidedTypes.fs重复了此练习,最初遇到了相同的问题。也就是说,一旦我将生成的类型用作客户端代码中的泛型类型参数,客户端代码就不会编译。即使使用 ProvidedTypes.fs,您也必须认识到 ProvidedTypeDefinition.DefineStaticParameters(相当于 ITypeProvider.GetStaticParameters)方法的处理程序必须考虑到可能会调用它传递生成的类型这一事实。

    关于f# - 使用F#生成类型提供程序类型作为泛型类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22085860/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com