【问题标题】:F# How to create an instance of a provided typeF#如何创建提供类型的实例
【发布时间】:2016-02-02 04:37:38
【问题描述】:

在我的first attempt 中创建类型提供程序,我有一个用于消息的ProvidedTypeDefinition:

// Message type
          let mTy = ProvidedTypeDefinition(asm, ns, message.Key, Some(typeof<ValueType>), 
                        HideObjectMethods = true, IsErased = false)
          // Direct buffer
          let bufferField = ProvidedField("_directBuffer", typeof<IDirectBuffer>)
          mTy.AddMember bufferField

          let mCtor1 = 
            ProvidedConstructor(
              [ProvidedParameter("buffer", typeof<IDirectBuffer>)], 
              InvokeCode = fun args ->
                match args with
                | [this;buffer] ->
                  Expr.FieldSet (this, bufferField, <@@ %%buffer:IDirectBuffer @@>)
                | _ -> failwith "wrong ctor params"
            )
          mTy.AddMember mCtor1

然后我需要在另一个提供类型的方法中创建该类型的实例。我正在这样做:

let mMethod = ProvidedMethod(message.Key, [ProvidedParameter("buffer", typeof<IDirectBuffer>)], mTy)
          mMethod.InvokeCode <- (fun [this;buffer] ->
                let c = mTy.GetConstructors().Last()
                Expr.NewObject(c, [ buffer ])
          )

ILSpy 显示该方法的以下等效 C# 代码:

public Car Car(IDirectBuffer buffer)
        {
            return new Car(buffer);
        }

它还表明Car 结构存在于测试程序集中(除非我访问Car 方法,否则此测试程序集构建正常):

但是当我尝试通过这样的方法创建汽车时:

type CarSchema = SbeProvider<"Path\to\SBETypeProvider\SBETypeProvider\Car.xml">
module Test =
  let carSchema = CarSchema()
  let car = carSchema.Car(null)

我收到以下错误:

  • 编译单元“tmp5CDE”中的模块/命名空间“SBETypeProvider”不包含命名空间、模块或类型“Car”

  • 在程序集“tmp5CDE”中找到对类型“SBETypeProvider.Car”的引用,但在该程序集中找不到该类型

我做错了什么?图片显示类型在这里。为什么我不能创建它?

我浏览了 GitHub 上的许多类型提供程序,但找不到一个明确的示例如何从另一个生成 ProvidedTypeDefinition

【问题讨论】:

    标签: f# type-providers


    【解决方案1】:

    这可能不是问题,但乍一看,line you linked 可能实际上是问题:

    let mTy = ProvidedTypeDefinition(asm, ns, message.Key, Some(typeof<ValueType>), 
                            HideObjectMethods = true, IsErased = false)
    

    此类型被添加到ty 提供的类型(将实际写入临时程序集的类型),因此不应自行指定程序集和命名空间。

    let mTy = ProvidedTypeDefinition(message.Key, Some(typeof<ValueType>), 
                            HideObjectMethods = true, IsErased = false)
    

    可能会更好。生成的类型虽然有点像魔法,但文档很少,所以有可能(很可能?)您可能会发现其他问题。

    一般来说,为了创建提供的类型,我通常最终会返回提供的构造函数作为一个值,然后可以使用Expr.Call 将其嵌入到其他属性/函数的调用代码中。这对于已擦除类型尤其重要,因为无论如何反射都不会对它们起作用。

    【讨论】:

    • 谢谢!一年,这个错误超载的问题是几个问题之一,可能是我问题的主要问题!我已经向 GitHub StarterPack 提交了另一个关于结构的问题。你的名字+图片告诉我你是主要贡献者。
    • 在浏览了大多数已知的 TP 并在 F# 大师的帮助下,我现在已经建立了一个更好的 TP 心智模型。重载是主要问题,但仍然有很多“微妙之处”,比如装配解析。为什么还是你说的“黑魔法”!? TP 是 F# 中最受赞誉、最酷、最独特和最强大的功能之一,但是当涉及到新的实现时——人们确实会迷失方向。而且他们在开始时确实像盲猫一样完全迷路了 :) 如何改进文档?
    猜你喜欢
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    相关资源
    最近更新 更多