gpt4 book ai didi

.net - 在 F# Interactive 中创建新的 AppDomain

转载 作者:行者123 更新时间:2023-12-04 12:45:16 24 4
gpt4 key购买 nike

我需要能够在 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 的介绍:

F# Interactive attempts to compile the code and, if successful, it executes the code and prints the signature of the types and values that it compiled.



主要问题在于编译步骤
typeof<myClass>.Assembly.FullName

输出:

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


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

意思是,它只存在于 fsi 的默认 appdomain 的内存中。下面的两个查找都抛出

System.NotSupportedException: The invoked member is not supported in a dynamic assembly.


asm.Location
asm.CodeBase

通常,您希望先持久化到磁盘,引用 remarks - 限制发送到远程应用程序域:

Some scenarios require a dynamic assembly to be created and executed in a remote application domain. Reflection emit does not allow a dynamic assembly to be emitted directly to a remote application domain. The solution is to emit the dynamic assembly in the current application domain, save the emitted dynamic assembly to disk, and then load the dynamic assembly into the remote application domain.



成功将动态程序集转换到 AssemblyBuilder会暴露一个 Save方法。不幸的是,这个工作流程也被封锁了。
open System.Reflection.Emit
let builder = asm :?> AssemblyBuilder

throw

System.InvalidCastException: Unable to cast object of type 'System.Reflection.Emit.InternalAssemblyBuilder' to type 'System.Reflection.Emit.AssemblyBuilder'



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

In the past, when InternalAssemblyBuilder was AssemblyBuilder, the untrusted user could down cast the Assembly to an AssemblyBuilder and emit code with the elevated permissions of the trusted code which origionally created the AssemblyBuilder via DefineDynamicAssembly. Today, this can no longer happen because the Assembly returned via AssemblyGetAssemblies() will be an InternalAssemblyBuilder.



或者,您可以反射(reflect)动态程序集中的类型和 reconstruct them使用 new AssemblyBuilder和其他 helper 在 System.Reflection.Emit命名空间,但这一切似乎有点乏味。

总而言之,按照当前实现的方式,您将在尝试将 fsi 生成的类型公开给其他域的流中游泳。

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

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com