繁体   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