I'm trying to write my first type provider and am wondering if someone could point where I am going wrong.
I've used the freebase sample to work from. I've tried to sift thru the essential bits to get something very basic instantiated but obviously missed something or not got it quite right (perhaps in relation to the namespace). I'm simply trying to get this line working
type tp = MyFirstTypeProvider.DataProvider<username="username",password="password",product=prodId>
Intellisense is seeing the DataProvider, but I'm getting squiggly saying that a reference to the type can be found the type could not be found in the assembly.
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()
Many thx in advance.
When I try compiling your type provider and reference it in a script file, the reference #r "provider.dll"
is underlined with a red squiggly that says:
The type provider 'MyFirstProvider.Types' reproted an error: The type provider constructor has thrown an exception: Object reference not set to an instance of an object.
You can debug such errors by starting a second instance of Visual Studio, and attaching the debugger to another instance (Debug -> Attach to Process) and opening the script file in the instance being debugged.
In the sample you posted here, the null reference exception occurs on this line:
let createDataContext = bfRuntimeInfo.DataContextType.GetMethod("_Create")
This is trying to access method that does not exist. I think the Freebase sample is relatively complicated starting point (here, it is using an object to represent the "data context" - you might want to follow that pattern, but I think it is easier to build it from scratch rather than adapting an existing code). I think a good starting point might be the Hello World type provider which is a lot simpler and just shows how to generate new types, properties and methods.