@@ -199,6 +199,7 @@ let loadAssembly (loadContext:AssemblyLoadContext) printDetails (assemInfo:Assem
199
199
if printDetails then tracefn " Unable to find assembly %A . (Error: %O )" assemInfo ex
200
200
None
201
201
202
+
202
203
let findAndLoadInRuntimeDeps ( loadContext : AssemblyLoadContext ) ( name : AssemblyName ) printDetails ( runtimeDependencies : AssemblyInfo list ) =
203
204
let strName = name.FullName
204
205
if printDetails then tracefn " Trying to resolve: %s " strName
@@ -219,33 +220,43 @@ let findAndLoadInRuntimeDeps (loadContext:AssemblyLoadContext) (name:AssemblyNam
219
220
| Some a ->
220
221
a.FullName = strName, ( Some ( None, a))
221
222
| 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
- | _ ->
237
223
#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
240
233
let location =
241
234
try Some assembly.Location
242
235
with e ->
243
236
if printDetails then tracefn " Could not get Location from '%s ': %O " strName e
244
237
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 ->
248
243
#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
+ | _ ->
249
260
false , None
250
261
match result with
251
262
| Some ( location, a) ->
@@ -260,22 +271,29 @@ let findAndLoadInRuntimeDeps (loadContext:AssemblyLoadContext) (name:AssemblyNam
260
271
if printDetails then tracefn " Could not resolve: %s " strName
261
272
null
262
273
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
+
263
290
#if NETSTANDARD1_ 6
264
291
// See https://github.com/dotnet/coreclr/issues/6411
265
292
type FakeLoadContext ( printDetails : bool , dependencies : AssemblyInfo list ) =
266
293
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
276
294
let allReferences = dependencies
277
295
override x.Load ( assem : AssemblyName ) =
278
- findAndLoadInRuntimeDeps x assem printDetails allReferences
296
+ findAndLoadInRuntimeDepsCached x assem printDetails allReferences
279
297
#endif
280
298
281
299
let fakeDirectoryName = " .fake"
0 commit comments