我需要能够在F#交互中创建新的AppDomain以便承载多个WPF应用程序。对于在已编译的F#应用程序中运行所需的功能,我没有任何问题,但是由于某种原因,似乎无法在F#交互式环境中运行该功能。

这是最简单的情况:

#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#交互式环境中正常工作?

最佳答案

docs的简介:



主要问题在于编译步骤

typeof<myClass>.Assembly.FullName

输出:



为了编译代码,fsi使用动态程序集来承载在 session 期间创建的所有类型。此处的关键要素是,其他域在不引用包含该程序集的情况下将无法解析这些类型。然而,事实证明,从其他应用程序域中获取程序集并非易事。主要是因为我们要处理动态装配。
let asm = typeof<myClass>.Assembly
asm.IsDynamic // val it : bool = true

这意味着,它仅存在于fsi的默认appdomain的内存中。下面的两个查找均抛出


asm.Location
asm.CodeBase

通常,您要先保留到磁盘,请参阅remarks-向远程应用程序域发出限制:



成功地将动态程序集转换为AssemblyBuilder将公开Save方法。不幸的是,该工作流程也已被封锁。
open System.Reflection.Emit
let builder = asm :?> AssemblyBuilder

throw



我们正在处理内部类型,显然我们不打算弄脏我们的手。从referencesource.microsoft.com:



另外,您可以使用new AssemblyBuilderSystem.Reflection.Emit命名空间中的其他帮助器来反射(reflect)动态程序集和reconstruct them中的类型,但这似乎有点乏味。

总结一下,当前实现的方式将使您流向流,以尝试将fsi生成的类型公开给其他域。

关于.net - 在F#Interactive中创建新的AppDomain,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50349820/

10-16 09:09