【问题标题】:F# Type Providers - nested properties instantiationF# Type Providers - 嵌套属性实例化
【发布时间】:2016-04-22 23:31:33
【问题描述】:

我正在尝试构建我的第一个类似玩具的类型提供程序。我想要实现的是动态生成动态生成类型的属性。

collection 
|> getItems
|> Seq.map(fun mapItem ->            
    let nestedType = ProvidedTypeDefinition(assembly, ns, "MyNestedType", None)
    let ctor = ProvidedConstructor(List.Empty)
    nestedType.AddMember ctor
    mapItem.Value 
        |> Seq.map(fun pair -> 
        ProvidedProperty(fst(pair), typeof<string>,
            GetterCode = fun [_] -> <@@ snd(pair) @@>))
        |> Seq.toList
        |> nestedType.AddMembers


    ProvidedProperty(mapItem.Key, nestedType,
        GetterCode = fun [map] ->   
            // ?? Runtime Exception   
            let inst = nestedType.GetConstructors().[0].Invoke([||])             
            <@@ inst @@>
                ))
    |> Seq.toList
    |> ty.AddMembers      

ty

我应该如何实例化动态生成的类型?

【问题讨论】:

    标签: f# type-providers quotations


    【解决方案1】:

    我假设这是一个擦除类型提供程序(这些提供程序很简单,因此它们是入门的更好选择)。如果不是这样,那就无视我的回答。

    GetterCode 中,您不需要创建提供的嵌套类型的实例。您只需要创建它被擦除到的类型的实例。

    在您的情况下,nestedType 被删除为 None,因此构造函数只需要创建一个 System.Object 值,因此您应该可以使用:

    ProvidedProperty(mapItem.Key, nestedType,
        GetterCode = fun [self] -> <@@ obj() @@>)
    

    实际上,您可能希望擦除某些类型,以便保留嵌套类型应该访问的一些数据。如果嵌套类型被擦除为MyRuntimeType,那么您可以编写:

    let parameter = mapItem.WhateverYouWantHere
    ProvidedProperty(mapItem.Key, nestedType,
        GetterCode = fun [self] -> <@@ MyRuntimeType(parameter) @@>)
    

    请注意,我使用let 来捕获原始parameter 类型的值,以便编译器可以序列化引用(不能在引用中捕获复杂的对象类型)。

    【讨论】:

    • 谢谢,我现在明白擦除类型的工作原理了。问题是我在类型提供程序的编译时不知道属性的名称,所以如果我没记错的话,我只能擦除对象。
    • 我想要实现的只是拥有这样的东西:providedType.dynamically_generated_prop.dynamically_generated_prop_nested,当使用提供者时
    【解决方案2】:

    您在这里尝试做的是实例化您的类型同时构建提供程序,然后将该新实例包含在属性的主体中。应该非常清楚的是,您不能在完成提供之前实例化提供的类型。

    您真正想要做的是获取您提供的构造函数并构建一个调用它的引用。你不能让编译器为你构建引用,因为为了让编译器编译引用的主体,它需要“看到”里面的所有类型/方法/函数,而你的类型还没有准备好。但是您可以使用Quotations.Expr 下的各种构造函数手动创建报价单。在这种情况下,NewObject 是合适的:

        GetterCode = fun [map] -> Expr.NewObject (ctor, [])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-30
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2014-08-12
      • 1970-01-01
      • 2012-08-05
      • 1970-01-01
      相关资源
      最近更新 更多