簡體   English   中英

在F#Interactive中創建新的AppDomain

[英]Creating new AppDomain in F# Interactive

我需要能夠在F#interactive中創建一個新的AppDomain,以便托管多個WPF應用程序。 我在編譯的F#應用程序中獲得必要的功能沒有任何問題,但由於某種原因使其在F#interactive中工作似乎不可能。

這是最簡單的案例: -

#r "PresentationCore.dll"
#r "PresentationFramework.dll"
#r "System.Xaml.dll"
#r "WindowsBase.dll"

open System    
open System.Threading
open System.Windows

type myClass() = 
    let domain = AppDomain.CreateDomain("another domain")

    //this function starts a WPF app
    let funct() =                
        let WPFStart() =
            let app = Application()
            let win = Window()            
            app.Run(win) |> ignore
        let thread = Thread WPFStart
        thread.IsBackground <- true
        thread.SetApartmentState ApartmentState.STA
        thread.Start()

    do CrossAppDomainDelegate(funct) |> domain.DoCallBack

myClass();;

我總是回過頭來做些什么

System.Runtime.Serialization.SerializationException: Type is not resolved 
for member 'FSI_0002+-ctor@24,FSI-ASSEMBLY, Version=0.0.0.0, 
Culture=neutral, PublicKeyToken=null'.
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at FSI_0002.myClass..ctor()
at <StartupCode$FSI_0005>.$FSI_0005.main@()
Stopped due to error

我需要做些什么才能在F#interactive中使用它?

來自文檔的介紹:

F#Interactive嘗試編譯代碼,如果成功,它將執行代碼並打印其編譯的類型和值的簽名。

主要問題在於編譯步驟

typeof<myClass>.Assembly.FullName

輸出:

 val it : string = "FSI-ASSEMBLY, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" 

為了編譯代碼, fsi使用動態程序集來托管會話期間創建的所有類型。 這里的關鍵元素是,如果沒有對包含程序集的引用,其他域將無法解析這些類型。 但是,從其他應用程序域中獲取程序集證明是非平凡的。 主要是因為我們正在處理動態裝配。

let asm = typeof<myClass>.Assembly 
asm.IsDynamic // val it : bool = true

這意味着,它只存在於FSI的默認應用程序域的內存。 下面的兩個查找都拋出

System.NotSupportedException:動態程序集中不支持調用的成員。

asm.Location
asm.CodeBase

通常,您希望首先保留到磁盤,引用注釋 - 發送到遠程應用程序域的限制

某些方案需要在遠程應用程序域中創建和執行動態程序集。 Reflection emit不允許將動態程序集直接發送到遠程應用程序域。 解決方案是在當前應用程序域中發出動態程序集,將發出的動態程序集保存到磁盤,然后將動態程序集加載到遠程應用程序域中。

成功將動態程序集強制轉換為AssemblyBuilder將公開Save方法。 不幸的是,這個工作流程也被封鎖了。

open System.Reflection.Emit
let builder = asm :?> AssemblyBuilder

拋出

System.InvalidCastException:無法將類型為“System.Reflection.Emit.InternalAssemblyBuilder”的對象強制轉換為“System.Reflection.Emit.AssemblyBuilder”

我們正在處理一種內部類型,顯然我們並沒有把手弄臟。 來自referencesource.microsoft.com

在過去,當InternalAssemblyBuilder是AssemblyBuilder時,不受信任的用戶可以將Assembly向下轉換為AssemblyBuilder,並使用通過DefineDynamicAssembly創建AssemblyBuilder的受信任代碼的提升權限發出代碼。 今天,這不再發生,因為通過AssemblyGetAssemblies()返回的程序集將是一個InternalAssemblyBuilder。

或者,您可以反映動態程序集中的類型,並使用System.Reflection.Emit命名空間中的new AssemblyBuilder和其他幫助程序重新構建它們 ,但這一切似乎都在乏味的一面。

總而言之,它目前實現的方式是你將游戲流試圖將fsi生成的類型暴露給其他域。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM