Я хочу написать программу, которая следит за изменениями .dll
. Когда происходит изменение, он должен загрузить сборку и вызвать функцию foo
внутри.
У меня есть код, который должен реализовать это, но он ведет себя странно. Иногда это работает. Иногда загружаемая сборка будет старой версии. Иногда это вызывает исключение BadImageFormatException
.
Вот код моей программы (это F#, но я думаю, что это общий вопрос .NET Core):
module HotReloadDemo
open System
open System.IO
open System.Reflection
[<EntryPoint>]
let main argv =
let assemblyPath = argv.[0] // Path to the .dll to watch
let mutable lastWriteTime = DateTime.MinValue
while true do
let writeTime =
if File.Exists assemblyPath
then
File.GetLastWriteTimeUtc assemblyPath
else
lastWriteTime
if writeTime > lastWriteTime
then
lastWriteTime <- writeTime
try
printfn "Last write time: %O " lastWriteTime
printfn "Waiting for the build to finish (this is a hack)... "
Threading.Thread.Sleep 10000 // 10s is plenty long enough for the build to finish
printfn "Loading assembly path from: %s " assemblyPath
let assembly = Assembly.LoadFrom assemblyPath
printfn "Got assembly: %O" (assembly.GetName ())
let foo : (Unit -> int) option =
assembly.GetExportedTypes()
|> Array.tryHead
|> Option.bind (fun t -> t.GetMethod "foo" |> Option.ofObj)
|> Option.map (fun m -> (fun () -> m.Invoke (null, Array.empty) :?> int))
match foo with
| Some foo ->
printfn "foo () = %O" (foo ())
| None ->
printfn "foo not found"
with exn ->
printfn "%O" exn
else
()
Threading.Thread.Sleep 1000
0
Затем у меня есть очень простая библиотека для просмотра в другом проекте, например:
module HotReload
let foo () =
123456
Чтобы проверить это, я запускаю программу «наблюдатель». Он успешно загружает и вызывает foo
.
Затем я модифицирую свою библиотеку (например, чтобы вернуть другое число) и создаю ее с помощью dotnet build
.
Наблюдатель обнаруживает изменение, снова загружает сборку и вызывает foo
, но печатает номер до изменения!
Затем я изменяю библиотеку снова с другим номером. Он обнаруживает изменение, но вылетает:
...
Loading assembly path from: ../hot-reload-lib/bin/Debug/netstandard2.0/hot-reload-lib.dll
System.BadImageFormatException: Could not load file or assembly '<Unknown>'. Index not found. (0x80131124)
File name: '<Unknown>'
at System.Runtime.Loader.AssemblyLoadContext.LoadFromPath(IntPtr ptrNativeAssemblyLoadContext, String ilPath, String niPath, ObjectHandleOnStack retAssembly)
at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String assemblyPath)
at System.Reflection.Assembly.LoadFrom(String assemblyFile)
...
Что здесь происходит?
dotnet --version
3.0.100
lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionic
BadImageFormatException
может быть связано с тем, что наблюдатель за файлом сработал до завершения записи файла. - person Asti   schedule 07.02.2020