@@ -199,6 +199,7 @@ let loadAssembly (loadContext:AssemblyLoadContext) printDetails (assemInfo:Assem
199199 if printDetails then tracefn " Unable to find assembly %A . (Error: %O )" assemInfo ex
200200 None
201201
202+
202203let findAndLoadInRuntimeDeps ( loadContext : AssemblyLoadContext ) ( name : AssemblyName ) printDetails ( runtimeDependencies : AssemblyInfo list ) =
203204 let strName = name.FullName
204205 if printDetails then tracefn " Trying to resolve: %s " strName
@@ -219,33 +220,43 @@ let findAndLoadInRuntimeDeps (loadContext:AssemblyLoadContext) (name:AssemblyNam
219220 | Some a ->
220221 a.FullName = strName, ( Some ( None, a))
221222 | None ->
222- match runtimeDependencies |> List.tryFind ( fun r -> r.FullName = strName) with
223- | Some a ->
224- true , loadAssembly loadContext printDetails a
225- | _ ->
226- let token = name.GetPublicKeyToken()
227- match runtimeDependencies
228- |> Seq.map ( fun r -> AssemblyName( r.FullName), r)
229- |> Seq.tryFind ( fun ( n , _ ) ->
230- n.Name = name.Name &&
231- ( isNull token || // When null accept what we have.
232- n.GetPublicKeyToken() = token)) with
233- | Some ( otherName, info) ->
234- // Then the version matches and the public token is null we still accept this as perfect match
235- ( isNull token && otherName.Version = name.Version), loadAssembly loadContext printDetails info
236- | _ ->
237223#if NETSTANDARD1_ 6
238- // One last option is to try and load from the default app-context...
239- try let assembly = AssemblyLoadContext.Default.LoadFromAssemblyName( name)
224+ // Check if we can resolve to a framework assembly.
225+ let result =
226+ try let assembly = AssemblyLoadContext.Default.LoadFromAssemblyName( name)
227+ let isFramework =
228+ assembly.GetCustomAttributes< AssemblyMetadataAttribute>()
229+ |> Seq.exists ( fun m -> m.Key = " .NETFrameworkAssembly" )
230+ if not isFramework then
231+ None
232+ else
240233 let location =
241234 try Some assembly.Location
242235 with e ->
243236 if printDetails then tracefn " Could not get Location from '%s ': %O " strName e
244237 None
245- true , Some ( location, assembly)
246- with e ->
247- if printDetails then tracefn " Could not find assembly in the default load-context: %s " strName
238+ Some ( location, assembly)
239+ with e -> None
240+ match result with
241+ | Some r -> true , Some r
242+ | None ->
248243#endif
244+ if printDetails then tracefn " Could not find assembly in the default load-context: %s " strName
245+ match runtimeDependencies |> List.tryFind ( fun r -> r.FullName = strName) with
246+ | Some a ->
247+ true , loadAssembly loadContext printDetails a
248+ | _ ->
249+ let token = name.GetPublicKeyToken()
250+ match runtimeDependencies
251+ |> Seq.map ( fun r -> AssemblyName( r.FullName), r)
252+ |> Seq.tryFind ( fun ( n , _ ) ->
253+ n.Name = name.Name &&
254+ ( isNull token || // When null accept what we have.
255+ n.GetPublicKeyToken() = token)) with
256+ | Some ( otherName, info) ->
257+ // Then the version matches and the public token is null we still accept this as perfect match
258+ ( isNull token && otherName.Version = name.Version), loadAssembly loadContext printDetails info
259+ | _ ->
249260 false , None
250261 match result with
251262 | Some ( location, a) ->
@@ -260,22 +271,29 @@ let findAndLoadInRuntimeDeps (loadContext:AssemblyLoadContext) (name:AssemblyNam
260271 if printDetails then tracefn " Could not resolve: %s " strName
261272 null
262273
274+ let findAndLoadInRuntimeDepsCached =
275+ let assemblyCache = System.Collections.Concurrent.ConcurrentDictionary<_, Assembly>()
276+ fun ( loadContext : AssemblyLoadContext ) ( name : AssemblyName ) printDetails ( runtimeDependencies : AssemblyInfo list ) ->
277+ let mutable wasCalled = false
278+ let result = assemblyCache.GetOrAdd( name.Name, ( fun _ ->
279+ wasCalled <- true
280+ findAndLoadInRuntimeDeps loadContext name printDetails runtimeDependencies))
281+ if not wasCalled then
282+ let loadedName = result.GetName()
283+ let isPerfectMatch = loadedName.Name = name.Name && loadedName.Version = name.Version
284+ if not isPerfectMatch then
285+ traceFAKE " Redirect assembly from '%A ' to previous loaded assembly '%A '" name loadedName
286+ else
287+ if printDetails then tracefn " Redirect assembly load to previously loaded assembly: %A " loadedName
288+ result
289+
263290#if NETSTANDARD1_ 6
264291// See https://github.com/dotnet/coreclr/issues/6411
265292type FakeLoadContext ( printDetails : bool , dependencies : AssemblyInfo list ) =
266293 inherit AssemblyLoadContext()
267- //let basePath = System.AppContext.BaseDirectory
268- //let references =
269- // System.IO.Directory.GetFiles(basePath, "*.dll")
270- // |> Seq.filter (fun r -> not (System.IO.Path.GetFileName(r).ToLowerInvariant().StartsWith("api-ms")))
271- // |> Seq.choose (fun r ->
272- // try Some (AssemblyInfo.ofLocation r)
273- // with e -> None)
274- // |> Seq.toList
275- //let allReferences = references @ dependencies
276294 let allReferences = dependencies
277295 override x.Load ( assem : AssemblyName ) =
278- findAndLoadInRuntimeDeps x assem printDetails allReferences
296+ findAndLoadInRuntimeDepsCached x assem printDetails allReferences
279297#endif
280298
281299let fakeDirectoryName = " .fake"
0 commit comments