我正试图编写我的第一个类型提供程序,我想知道是否有人可以指出我出错的地方。
我已经使用了freebase样本来工作。我试图筛选必要的部分,以获得一些非常基本的实例化,但显然遗漏了一些东西或没有完全正确(可能与名称空间有关)。我只是想让这行正常工作
type tp = MyFirstTypeProvider.DataProvider<username="username",password="password",product=prodId>
智能感知正在查看数据提供程序,但是我正在说可以找到对类型的引用,而在程序集中无法找到类型。
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()
提前谢谢。
当我尝试编译您的类型提供程序并在脚本文件中引用它时,引用#r "provider.dll"
用红色曲线下划线表示:
类型提供商MyFirstProvider。类型提供程序的构造函数抛出了一个异常:对象引用未设置为对象的实例。
您可以通过启动第二个Visual Studio实例,并将调试器附加到另一个实例(debug -> Attach to Process)并在被调试的实例中打开脚本文件来调试此类错误。
在您在这里发布的示例中,空引用异常发生在这一行:
let createDataContext = bfRuntimeInfo.DataContextType.GetMethod("_Create")
试图访问一个不存在的方法。我认为Freebase示例的起点相对复杂(这里,它使用一个对象来表示"数据上下文"——你可能想要遵循这个模式,但我认为从头开始构建它比改编现有代码更容易)。我认为可以从Hello World类型提供程序开始,它简单得多,只展示了如何生成新的类型、属性和方法。
我建议,如果你正在寻找一个简单的类型提供程序的例子,看看文件系统类型提供程序。这是一个很好的起点,因为它没有状态,也没有依赖管理要照顾。
至于为什么这个有一个无法找到的dll,我认为这是因为这个dll必须从您的类型提供程序的dll所在的位置看到。例如,在同一个目录中。(您可以尝试在构建过程中设置"copy local"?)