Поставщик типа не виден отражением

Я пытаюсь написать своего поставщика первого типа, и мне интересно, может ли кто-нибудь указать, где я ошибаюсь.

Я использовал образец 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()

Большое спасибо заранее.


person Simon Woods    schedule 23.03.2013    source источник


Ответы (2)


Когда я пытаюсь скомпилировать ваш поставщик типов и сослаться на него в файле скрипта, ссылка #r "provider.dll" подчеркнута красной волнистой линией, которая говорит:

Поставщик типов MyFirstProvider.Types повторил ошибку: конструктор поставщика типов вызвал исключение: ссылка на объект не указывает на экземпляр объекта.

Вы можете отлаживать такие ошибки, запустив второй экземпляр Visual Studio, подключив отладчик к другому экземпляру (Отладка -> Присоединить к процессу) и открыв файл сценария в отлаживаемом экземпляре.

В образце, который вы разместили здесь, в этой строке возникает исключение нулевой ссылки:

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

Это попытка доступа к несуществующему методу. Я думаю, что образец Freebase является относительно сложной отправной точкой (здесь он использует объект для представления «контекста данных» — вы можете следовать этому шаблону, но я думаю, что проще создать его с нуля, чем адаптировать существующий). код). Я думаю, что хорошей отправной точкой может быть поставщик Hello World, который намного проще и просто показывает, как генерировать новые типы, свойства и методы.

person Tomas Petricek    schedule 23.03.2013
comment
Спасибо большое. Я не полностью изучил два способа создания экземпляра поставщика типа freebase — с ключом API и без него — MyProvider.Data и MyProvider.DataProvider‹[params›. Думаю, я как бы ожидал поведения типа перегрузок. Как только эта копейка упадет, я смогу заставить эту штуку работать! Большое спасибо еще раз - person Simon Woods; 24.03.2013

Я бы посоветовал, если вы ищете простой пример поставщика типов, посмотреть ссылку Поставщик типа файловой системы Это хорошее место для начала, так как у него нет состояния и управления зависимостями, о которых нужно заботиться.

Что касается того, почему у этого есть dll, который он не может найти, я думаю, это потому, что эта dll должна быть видна из того места, где находится dll вашего поставщика типов. То есть, например, в том же каталоге. (Вы можете попробовать установить «копировать локально» в процессе сборки?)

person nicolas    schedule 23.03.2013