F# 类型提供程序引用自定义类型
F# Type Provider Referencing Custom Types
我正在构建一个简单的类型提供程序,但我似乎 运行在引用我创建的类型时遇到了问题。例如,给定
namespace Adder
type Summation = Summation of int
module QuickAdd =
let add x y = x + y |> Summation
我想让下面的测试用例通过:
module Adder.Tests
open Adder
open NUnit.Framework
type Simple = QuickAddProvider<1, 2>
[<Test>]
let ``Simple sample is 3`` () =
let foo = Simple()
Assert.AreEqual(foo.Sample, Summation 3)
使用以下类型的提供商:
namespace Adder
open Microsoft.FSharp.Core.CompilerServices
open ProviderImplementation.ProvidedTypes
open System.Reflection
[<TypeProvider>]
type public QuickAddProvider (config : TypeProviderConfig) as this =
inherit TypeProviderForNamespaces ()
let ns = "Adder"
let asm = Assembly.GetExecutingAssembly()
let paraProvTy = ProvidedTypeDefinition(asm, ns, "QuickAddProvider", Some typeof<obj>)
let buildTypes (typeName:string) (args:obj[]) =
let num1 = args.[0] :?> int
let num2 = args.[1] :?> int
let tpType = ProvidedTypeDefinition(asm, ns, typeName, Some typeof<obj>)
let result = QuickAdd.add num1 num2
let orig = ProvidedProperty("Sample", typeof<Summation>, GetterCode = (fun args -> <@@ result @@>))
tpType.AddMember(orig)
tpType.AddMember(ProvidedConstructor([], InvokeCode = (fun args -> <@@ () @@>)))
tpType
let parameters =
[ProvidedStaticParameter("Num1", typeof<int>)
ProvidedStaticParameter("Num2", typeof<int>)]
do paraProvTy.DefineStaticParameters(parameters, buildTypes)
do this.AddNamespace(ns, [paraProvTy])
[<TypeProviderAssembly>]
do()
我运行在测试文件中遇到意外错误:
The type provider 'Adder.QuickAddProvider' reported an error in the context of provided type 'Adder.QuickAddProvider,Num1="1",Num2="2"', member 'get_Sample'. The error: Unsupported constant type 'Adder.Summation'
生成的文件中存在以下错误:
The type "Summation" is not defined
The namespace or module "Adder" is not defined
当用 int
替换 Summation
类型时,测试用例编译并通过,所以我知道我的类型提供者并没有错。我需要以某种方式 "import" 在某处输入 Summation
吗?
此错误通常意味着您正在创建包含自定义类型值的报价单。类型提供者中的引号只能包含基本类型的值——编译器知道如何序列化这些——但它不能处理自定义类型。
在代码片段中,这发生在这里:
let result = QuickAdd.add num1 num2
let orig = ProvidedProperty("Sample", typeof<Summation>, GetterCode = (fun args ->
<@@ result @@>))
此处,GetterCode
returns 引用包含不支持的 Summation
类型的值。为了使这项工作有效,您可以做各种事情 - 通常,您需要想出一些其他的引用表达式来产生您想要的值。
一个选择是在报价内而不是在报价外进行计算:
<@@ QuickAdd.add num1 num2 @@>
另一种选择是在引文中重新创建 Summation
值:
let (Summation n) = result
<@@ Summation n @@>
这是可行的,因为它只需要序列化原始 int
值,然后生成对 Summation
案例构造函数的调用。
我正在构建一个简单的类型提供程序,但我似乎 运行在引用我创建的类型时遇到了问题。例如,给定
namespace Adder
type Summation = Summation of int
module QuickAdd =
let add x y = x + y |> Summation
我想让下面的测试用例通过:
module Adder.Tests
open Adder
open NUnit.Framework
type Simple = QuickAddProvider<1, 2>
[<Test>]
let ``Simple sample is 3`` () =
let foo = Simple()
Assert.AreEqual(foo.Sample, Summation 3)
使用以下类型的提供商:
namespace Adder
open Microsoft.FSharp.Core.CompilerServices
open ProviderImplementation.ProvidedTypes
open System.Reflection
[<TypeProvider>]
type public QuickAddProvider (config : TypeProviderConfig) as this =
inherit TypeProviderForNamespaces ()
let ns = "Adder"
let asm = Assembly.GetExecutingAssembly()
let paraProvTy = ProvidedTypeDefinition(asm, ns, "QuickAddProvider", Some typeof<obj>)
let buildTypes (typeName:string) (args:obj[]) =
let num1 = args.[0] :?> int
let num2 = args.[1] :?> int
let tpType = ProvidedTypeDefinition(asm, ns, typeName, Some typeof<obj>)
let result = QuickAdd.add num1 num2
let orig = ProvidedProperty("Sample", typeof<Summation>, GetterCode = (fun args -> <@@ result @@>))
tpType.AddMember(orig)
tpType.AddMember(ProvidedConstructor([], InvokeCode = (fun args -> <@@ () @@>)))
tpType
let parameters =
[ProvidedStaticParameter("Num1", typeof<int>)
ProvidedStaticParameter("Num2", typeof<int>)]
do paraProvTy.DefineStaticParameters(parameters, buildTypes)
do this.AddNamespace(ns, [paraProvTy])
[<TypeProviderAssembly>]
do()
我运行在测试文件中遇到意外错误:
The type provider 'Adder.QuickAddProvider' reported an error in the context of provided type 'Adder.QuickAddProvider,Num1="1",Num2="2"', member 'get_Sample'. The error: Unsupported constant type 'Adder.Summation'
生成的文件中存在以下错误:
The type "Summation" is not defined
The namespace or module "Adder" is not defined
当用 int
替换 Summation
类型时,测试用例编译并通过,所以我知道我的类型提供者并没有错。我需要以某种方式 "import" 在某处输入 Summation
吗?
此错误通常意味着您正在创建包含自定义类型值的报价单。类型提供者中的引号只能包含基本类型的值——编译器知道如何序列化这些——但它不能处理自定义类型。
在代码片段中,这发生在这里:
let result = QuickAdd.add num1 num2
let orig = ProvidedProperty("Sample", typeof<Summation>, GetterCode = (fun args ->
<@@ result @@>))
此处,GetterCode
returns 引用包含不支持的 Summation
类型的值。为了使这项工作有效,您可以做各种事情 - 通常,您需要想出一些其他的引用表达式来产生您想要的值。
一个选择是在报价内而不是在报价外进行计算:
<@@ QuickAdd.add num1 num2 @@>
另一种选择是在引文中重新创建 Summation
值:
let (Summation n) = result
<@@ Summation n @@>
这是可行的,因为它只需要序列化原始 int
值,然后生成对 Summation
案例构造函数的调用。