类型提供程序没有被反射看到

时间:2013-03-23 16:08:45

标签: reflection f# type-providers f#-3.0

我正在尝试编写我的第一个类型提供商,并且想知道是否有人可以指出我出错的地方。

我已经使用了freebase示例。我试图通过基本的位来筛选一些非常基本的实例化但显然错过了一些东西或者没有把它弄得很正确(可能与命名空间有关)。我只是想让这条线工作

type tp = MyFirstTypeProvider.DataProvider<username="username",password="password",product=prodId>

Intellisense正在看DataProvider,但是我正在变得潦草地说,可以找到对该类型的引用,在程序集中找不到该类型。

namespace MyFirstProvider

type internal MyFirstRuntimeInfo(config: TypeProviderConfig) =
    let runtimeAssembly = Assembly.LoadFrom(config.RuntimeAssembly)

    member val DataContextType = runtimeAssembly.GetType("MyFirstProvider.Runtime.DataContext")
    member this.RuntimeAssembly = runtimeAssembly

// This type defines the type provider. When compiled to a DLL, it can be added
// as a reference to an F# command-line compilation, script, or project.
[<TypeProvider>]
type public Types(config: TypeProviderConfig) as this = 
    inherit TypeProviderForNamespaces()

    let bfRuntimeInfo = MyFirstRuntimeInfo(config)

    let rootNamespace = "MyFirstProvider"

    let defaultUsername = "xxxxxxxxxxx"
    let defaultPassword = "yyyyyyyyyy"
    let defaultProductId = -1    
    let defaultToken = "none"

    let createDataContext = bfRuntimeInfo.DataContextType.GetMethod("_Create")

    let createTypes(username, password, productId, rootTypeName) =                       let bf  = new MyFirstProvider.Requests.Queries(defaultToken)
    let schema = new MyFirstProvider.Schema.SchemaConnection(bf)
    let rootType = ProvidedTypeDefinition(bfRuntimeInfo.RuntimeAssembly,rootNamespace,rootTypeName,baseType=Some typeof<obj>, HideObjectMethods=true)
    let theServiceType = ProvidedTypeDefinition("Service",baseType=Some bfRuntimeInfo.DataContextType, HideObjectMethods=true)
    let theServiceTypesClass = ProvidedTypeDefinition("ServiceTypes",baseType=Some typeof<obj>,HideObjectMethods=true)   
    theServiceTypesClass.AddMembers [ theServiceType ]     
    rootType.AddMembers [ theServiceTypesClass  ]
    rootType.AddMembersDelayed (fun () -> 
        [ yield ProvidedMethod ("GetDataContext", [], theServiceType, IsStaticMethod=true,
                                InvokeCode = (fun _args -> Expr.Call(createDataContext, [  Expr.Value defaultUsername; Expr.Value defaultPassword; Expr.Value defaultProductId ])))
        ])        
    rootType

    let MyFirstType = createTypes(defaultUsername, defaultPassword, defaultProductId, "Data")
    let paramMyFirstType = ProvidedTypeDefinition(bfRuntimeInfo.RuntimeAssembly, rootNamespace, "DataProvider", Some(typeof<obj>), HideObjectMethods = true)
    let usernameParam = ProvidedStaticParameter("username", typeof<string>, defaultUsername)
    let passwordParam = ProvidedStaticParameter("password", typeof<string>, defaultPassword)
    let productIdParam = ProvidedStaticParameter("productId", typeof<int>, defaultProductId)

    do    paramMyFirstType.DefineStaticParameters([usernameParam;passwordParam;productIdParam], fun typeName providerArgs ->
        let username = (providerArgs.[0] :?> string)
        let password = (providerArgs.[1] :?> string)
        let productId = (providerArgs.[2] :?> int)
        createTypes(username, password, productId, typeName))

    do
        this.AddNamespace(rootNamespace, [MyFirstType ] )
        this.AddNamespace(rootNamespace, [paramMyFirstType ] )

[<assembly:TypeProviderAssembly>] 
do()

提前很多。

2 个答案:

答案 0 :(得分:3)

当我尝试编译您的类型提供程序并在脚本文件中引用它时,引用#r "provider.dll"带有一个红色波浪形的下划线,上面写着:

  

类型提供程序'MyFirstProvider.Types'重新引发错误:类型提供程序构造函数引发了异常:对象引用未设置为对象的实例。

您可以通过启动Visual Studio的第二个实例并将调试器附加到另一个实例(Debug - &gt; Attach to Process)并在正在调试的实例中打开脚本文件来调试此类错误。

在此处发布的示例中,此行上出现空引用异常:

let createDataContext = bfRuntimeInfo.DataContextType.GetMethod("_Create")

这是尝试访问不存在的方法。我认为Freebase示例是相对复杂的起点(这里,它使用一个对象来表示“数据上下文”) - 您可能希望遵循该模式,但我认为从头开始构建它而不是调整现有模型更容易码)。我认为一个好的起点可能是Hello World type provider更简单,只是展示了如何生成新的类型,属性和方法。

答案 1 :(得分:2)

我建议,如果你正在寻找一个类型提供者的简单例子,看看File System type provider这是一个很好的起点,因为它没有状态,也没有依赖管理来处理。

至于为什么这个有一个它无法找到的dll,我认为这是因为必须从你的类型提供者的dll所在的位置看到这个dll。也就是说,例如,在同一目录中。 (您可以尝试在构建过程中设置“复制本地”吗?)