Я хочу написать программу, которая следит за изменениями .dll
. Когда происходит изменение, он должен загрузить сборку и вызвать функцию foo
внутри.
У меня есть код, который должен это реализовать, но он ведет себя странно. Иногда это работает. Иногда загружаемая сборка будет старой версией. Иногда он вызывает исключение BadImageFormatException
.
Вот мой программный код (это F #, но я думаю, что это общий. NET Основной вопрос):
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