[英]F# Type Provider Referencing Custom Types
I'm constructing a simple type provider, but I seem to be running into problems when referencing types I created. 我正在构建一个简单的类型提供程序,但在引用我创建的类型时,我似乎遇到了问题。 For instance, given
例如,给定
namespace Adder
type Summation = Summation of int
module QuickAdd =
let add x y = x + y |> Summation
I want to make the following test case pass: 我想让以下测试用例通过:
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)
With the following type provider: 使用以下类型提供程序:
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()
I run into unexpected errors in the test file: 我在测试文件中遇到意外错误:
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'
With the following errors in the generated file: 在生成的文件中出现以下错误:
The type "Summation" is not defined
The namespace or module "Adder" is not defined
The test case compiles and passes when replacing the Summation
type with int
, so I know my type provider isn't terribly wrong. 当用
int
替换Summation
类型时,测试用例编译并传递,所以我知道我的类型提供者并不是非常错误。 Do I need to somehow "import" the Summation
type somewhere? 我是否需要以某种方式“导入”
Summation
类型?
This error usually means that you are creating a quotation that contains a value of custom type. 此错误通常表示您正在创建包含自定义类型值的报价。 The quotations in type providers can only contain values of primitive types - the compiler knows how to serialize these - but it cannot handle custom types.
类型提供程序中的引用只能包含基本类型的值 - 编译器知道如何序列化这些 - 但它无法处理自定义类型。
In the snippet, this happens here: 在代码段中,这发生在这里:
let result = QuickAdd.add num1 num2
let orig = ProvidedProperty("Sample", typeof<Summation>, GetterCode = (fun args ->
<@@ result @@>))
Here, the GetterCode
returns a quotation containing value of type Summation
which is not supported. 这里,
GetterCode
返回类型的含报价值Summation
不被支持。 To make this work, you can do various things - generally, you'll need to come up with some other quoted expression that produces the value you want. 为了使这项工作,您可以做各种事情 - 通常,您需要提出一些产生您想要的值的其他引用表达式。
One option is to do the calculation inside the quotation rather than outside: 一种选择是做报价单内的计算,而不是外面:
<@@ QuickAdd.add num1 num2 @@>
The other option would be to re-create the Summation
value in the quotation: 另一种选择是在报价单中重新创建
Summation
值:
let (Summation n) = result
<@@ Summation n @@>
This works, because it only needs to serialize a primitive int
value and then generate a call to the Summation
case constructor. 这是有效的,因为它只需序列化一个原始
int
值,然后生成对Summation
case构造函数的调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.