Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For an F# Type Provider, how do I do a binding redirect for a dependent assembly?

I'm working on an F# Type Provider that has a dependency on FParsec 0.9.2.0. It depends on FSharp.Core 4.0.0.0. When I try to use the F# Type Provider, I get this error:

{"Could not load file or assembly 'FSharp.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.":"FSharp.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"}

=== Pre-bind state information ===
LOG: DisplayName = FSharp.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a (Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/
LOG: Initial PrivatePath = NULL
Calling assembly : FParsec, Version=0.9.2.0, Culture=neutral, PublicKeyToken=e5c8267bb3bd1265.

I tried adding a Froto.Gen.dll.config and a FParsec.dll.config, both that had this in it:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="4.0.0.0" newVersion="4.3.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

No luck. Any ideas? My next plan of action is to build a new FParsec.dll, but that isn't always going to work.

like image 545
Cameron Taggart Avatar asked Nov 19 '12 23:11

Cameron Taggart


2 Answers

Have you tried overriding AppDomain.CurrentDomain.AssemblyResolve and doing an explicit Assembly.LoadFrom on the location of FSharp.Core 4.3.0.0 when args.Name requires 4.0.0.0?

like image 142
Gustavo Guerra Avatar answered Nov 06 '22 11:11

Gustavo Guerra


You can actually define your own assembly resolver in your type provider.

If you override the ResolveAssembly method you can provide your own assembly resolution scheme. The default implementation is fairly simple:

default this.ResolveAssembly(args) = 
    let expectedName = (AssemblyName(args.Name)).Name + ".dll"
    let expectedLocationOpt = 
        probingFolders 
        |> Seq.map (fun f -> IO.Path.Combine(f, expectedName))
        |> Seq.tryFind IO.File.Exists
    match expectedLocationOpt with
    | Some f -> Assembly.LoadFrom f
    | None -> null

Also you can add a probing path to influence the locations that are checked for assembly resolution:

[<TypeProvider>] 
type MyProvider(config: TypeProviderConfig) as this = 
    inherit TypeProviderForNamespaces()
    do this.RegisterProbingFolder "/Developer/MonoTouch/usr/lib/mono/2.1/"
    ...
like image 28
7sharp9 Avatar answered Nov 06 '22 12:11

7sharp9