5 people like it.

AssemblyResolver.fs

Assembly resolver implementation required by .NET Framework MSBuild task to resolve different versions of assembly because of missing binding redirect functionality in MSBuild.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
open System
open System.Diagnostics
open System.IO
open System.Reflection

module private ValueOption =
    let mapNone initializer =
        function
        | ValueSome value -> ValueSome value
        | ValueNone -> initializer ()

/// <summary>
/// Considers a path to load for satisfying an assembly ref and loads it
/// if the file exists and version is sufficient.
/// </summary>
/// <param name="filePath">Path to consider for load</param>
/// <param name="minimumVersion">Minimum version to consider</param>
/// <returns>loaded assembly voption</returns>
let private probe(filePath: string, minimumVersion: Version) : Assembly voption =
    if File.Exists(filePath) then
        let name = AssemblyName.GetAssemblyName(filePath)
        if name.Version >= minimumVersion
        then ValueSome (Assembly.Load(name))
        else ValueNone
    else ValueNone

let private loadFromCurrentDirectory fileName version =
    Debug.WriteLine($"Considering {fileName}")
    probe(fileName, version)

let private loadFromExecutingAssembly fileName version =
    match Assembly.GetExecutingAssembly().Location with
    | null -> ValueNone
    | assemblyPath ->
        let probingPath = Path.Combine(Path.GetDirectoryName(assemblyPath), fileName)
        Debug.WriteLine($"Considering {probingPath} based on ExecutingAssembly")
        probe(probingPath, version)

let private loadFromAppDomain fileName version =
    let probingPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName)
    Debug.WriteLine($"Considering {probingPath} based on BaseDirectory")
    probe(probingPath, version)

let private loadFromRequestingAssemblyPath version fileName assemblyPath =
     let probingPath = Path.Combine(Path.GetDirectoryName(assemblyPath), fileName)
     Debug.WriteLine($"Considering {probingPath} based on RequestingAssembly")
     probe(probingPath, version)

let private onAssemblyResolve(args: ResolveEventArgs) : Assembly =
    // apply any existing policy
    let referenceName = new AssemblyName(AppDomain.CurrentDomain.ApplyPolicy(args.Name))
    let version = referenceName.Version
    let fileName = referenceName.Name + ".dll"

    args.RequestingAssembly
    |> ValueOption.ofObj
    |> ValueOption.map (fun assemblyPath -> assemblyPath.Location)
    |> ValueOption.bind (loadFromRequestingAssemblyPath version fileName)
    |> ValueOption.mapNone (fun () -> loadFromAppDomain fileName version)
    |> ValueOption.mapNone (fun () -> loadFromExecutingAssembly fileName version)
    |> ValueOption.mapNone (fun () -> loadFromCurrentDirectory fileName version)
    |> ValueOption.defaultValue null

[<CompiledName("Enable")>]
let public enable() = AppDomain.CurrentDomain.add_AssemblyResolve(fun _ args -> onAssemblyResolve(args))
namespace System
namespace System.Diagnostics
namespace System.IO
namespace System.Reflection
Multiple items
module ValueOption

from Microsoft.FSharp.Core

--------------------
[<Struct>]
type ValueOption<'T> =
  | ValueNone
  | ValueSome of 'T
    member IsNone : bool
    member IsSome : bool
    member Value : 'T
    static member Some : value:'T -> 'T voption
    static member None : 'T voption
    static member op_Implicit : value:'T -> 'T voption
val private mapNone : initializer:(unit -> 'a voption) -> _arg1:'a voption -> 'a voption
val initializer : (unit -> 'a voption)
union case ValueOption.ValueSome: 'T -> ValueOption<'T>
val value : 'a
union case ValueOption.ValueNone: ValueOption<'T>
val private probe : filePath:string * minimumVersion:Version -> Assembly voption


 <summary>
 Considers a path to load for satisfying an assembly ref and loads it
 if the file exists and version is sufficient.
 </summary>
 <param name="filePath">Path to consider for load</param>
 <param name="minimumVersion">Minimum version to consider</param>
 <returns>loaded assembly voption</returns>
val filePath : string
Multiple items
val string : value:'T -> string

--------------------
type string = String
val minimumVersion : Version
Multiple items
type Version =
  new : unit -> Version + 4 overloads
  member Build : int
  member Clone : unit -> obj
  member CompareTo : version:obj -> int + 1 overload
  member Equals : obj:obj -> bool + 1 overload
  member GetHashCode : unit -> int
  member Major : int
  member MajorRevision : int16
  member Minor : int
  member MinorRevision : int16
  ...

--------------------
Version() : Version
Version(version: string) : Version
Version(major: int, minor: int) : Version
Version(major: int, minor: int, build: int) : Version
Version(major: int, minor: int, build: int, revision: int) : Version
type Assembly =
  member CodeBase : string
  member CreateInstance : typeName:string -> obj + 2 overloads
  member CustomAttributes : IEnumerable<CustomAttributeData>
  member DefinedTypes : IEnumerable<TypeInfo>
  member EntryPoint : MethodInfo
  member Equals : o:obj -> bool
  member EscapedCodeBase : string
  member ExportedTypes : IEnumerable<Type>
  member FullName : string
  member GetCustomAttributes : inherit:bool -> obj[] + 1 overload
  ...
[<Struct>]
type 'T voption = ValueOption<'T>
type File =
  static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
  static member AppendAllLinesAsync : path:string * contents:IEnumerable<string> * ?cancellationToken:CancellationToken -> Task + 1 overload
  static member AppendAllText : path:string * contents:string -> unit + 1 overload
  static member AppendAllTextAsync : path:string * contents:string * ?cancellationToken:CancellationToken -> Task + 1 overload
  static member AppendText : path:string -> StreamWriter
  static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
  static member Create : path:string -> FileStream + 2 overloads
  static member CreateText : path:string -> StreamWriter
  static member Decrypt : path:string -> unit
  static member Delete : path:string -> unit
  ...
File.Exists(path: string) : bool
val name : AssemblyName
Multiple items
type AssemblyName =
  new : unit -> AssemblyName + 1 overload
  member Clone : unit -> obj
  member CodeBase : string with get, set
  member ContentType : AssemblyContentType with get, set
  member CultureInfo : CultureInfo with get, set
  member CultureName : string with get, set
  member EscapedCodeBase : string
  member Flags : AssemblyNameFlags with get, set
  member FullName : string
  member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
  ...

--------------------
AssemblyName() : AssemblyName
AssemblyName(assemblyName: string) : AssemblyName
AssemblyName.GetAssemblyName(assemblyFile: string) : AssemblyName
Assembly.Load(rawAssembly: byte []) : Assembly
Assembly.Load(assemblyRef: AssemblyName) : Assembly
Assembly.Load(assemblyString: string) : Assembly
Assembly.Load(rawAssembly: byte [], rawSymbolStore: byte []) : Assembly
val private loadFromCurrentDirectory : fileName:'a -> version:'b -> unit
val fileName : 'a
val version : 'b
type Debug =
  static member Assert : condition:bool -> unit + 3 overloads
  static member AutoFlush : bool with get, set
  static member Close : unit -> unit
  static member Fail : message:string -> unit + 1 overload
  static member Flush : unit -> unit
  static member Indent : unit -> unit
  static member IndentLevel : int with get, set
  static member IndentSize : int with get, set
  static member Print : message:string -> unit + 1 overload
  static member SetProvider : provider:DebugProvider -> DebugProvider
  ...
Debug.WriteLine(value: obj) : unit
Debug.WriteLine(message: string) : unit
Debug.WriteLine(message: string, category: string) : unit
Debug.WriteLine(format: string, [<ParamArray>] args: obj []) : unit
Debug.WriteLine(value: obj, category: string) : unit
Raw view Test code New version

More information

Link:http://fssnip.net/83w
Posted:2 years ago
Author:anthony-mi
Tags: #msbuild , #assemblyresolver , #bindingredirect