Search code examples
f#type-providersassembly-binding-redirectpaket

F# Type Provider dependency resolution - "Could not load file or assembly..."


I am encountering a "Could not load file or assembly... ... The system could not find the file specified" error when trying to consume my type provider.

The error appears on building the consuming application but does not show up as a 'red squiggly' in visual studio prior to the build.

I have copied my TP below but the issue occurs inside the Database.listDbs call and I strongly suspect the issue is not the code below but how I am packaging the dependencies.

I call into the Microsoft.Azure.DocumentDB package which, in turn, depends on Newtonsoft.Json. It is the Newtonsoft.Json package which cannot be found. I am using Paket to manage dependencies and have redirects on.

The full code (including all the paket files) is on github here: https://github.com/stewart-r/AzureDocumentDbTypeProvider/tree/dependency-issue

I found this question which seems very similar but the solution did not make any difference.

My TP code is as follows:

namespace ProviderImplementation

open ProviderImplementation.ProvidedTypes
open Microsoft.FSharp.Core.CompilerServices
open System.Reflection
open System
open Config
open Database

[<TypeProvider>]
type public DocumentDbTypeProvider(config: TypeProviderConfig) as this = 
    inherit TypeProviderForNamespaces()

    let thisAssembly = Assembly.GetExecutingAssembly()
    let docDbType = ProvidedTypeDefinition(thisAssembly,namespaceName,"DocumentDbTypeProvider", baseType = Some typeof<obj>)

    let initFn (typeName : string) (args : obj []) = 
        let acProvidedType = ProvidedTypeDefinition(thisAssembly, namespaceName, typeName, baseType = Some typeof<obj>)
        acProvidedType.AddMember(ProvidedConstructor(parameters = [], InvokeCode = (fun args -> <@@ null @@>)))

        let getDbProperties () = 
            Database.listDbs (args.[0] :?> string) (args.[1]:?> string)
            |> List.map(fun d -> new ProvidedProperty(d.Name, typeof<string>, IsStatic = true, GetterCode = (fun _ -> <@@ "Test db name" @@>)))
        acProvidedType.AddMembers(getDbProperties())
        acProvidedType

    let parameters = 
        [ ProvidedStaticParameter("accountEndPointUri", typeof<string>, String.Empty)
          ProvidedStaticParameter("accountKey", typeof<string>, String.Empty)]

    do
        docDbType.DefineStaticParameters(parameters,initFn)
        this.AddNamespace(namespaceName,[docDbType])

[<TypeProviderAssembly>]
do ()

Solution

  • This is a binding redirect issue - you need to handle the BR inside the type provider. Alternatively, you can restrict the dependencies to the minimum version needed by your direct dependency e.g. DocumentDB.