Fun*_*rst 7 .net wpf f# 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();;
Run Code Online (Sandbox Code Playgroud)
我总是回过头来做些什么
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
Run Code Online (Sandbox Code Playgroud)
我需要做些什么才能在F#interactive中使用它?
文档介绍:
F# Interactive 尝试编译代码,如果成功,它将执行代码并打印其编译的类型和值的签名。
主要问题在于编译步骤
typeof<myClass>.Assembly.FullName
Run Code Online (Sandbox Code Playgroud)
输出:
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)
意思是,它仅存在于fsi的默认应用程序域的内存中。下面的两个查找都会抛出
System.NotSupportedException:动态程序集中不支持调用的成员。
asm.Location
asm.CodeBase
Run Code Online (Sandbox Code Playgroud)
通常,您希望首先保留到磁盘,参考注释-发送到远程应用程序域的限制:
某些方案需要在远程应用程序域中创建和执行动态程序集。反射发出不允许将动态程序集直接发出到远程应用程序域。解决方案是在当前应用程序域中发出动态程序集,将发出的动态程序集保存到磁盘,然后将动态程序集加载到远程应用程序域中。
成功地将动态程序集转换为AssemblyBuilder将公开一个Save方法。不幸的是,这个工作流程也被封锁了。
open System.Reflection.Emit
let builder = asm :?> AssemblyBuilder
Run Code Online (Sandbox Code Playgroud)
投掷
System.InvalidCastException:无法将类型“System.Reflection.Emit.InternalAssemblyBuilder”的对象强制转换为类型“System.Reflection.Emit.AssemblyBuilder”
我们正在处理一个内部类型,显然我们不打算亲自动手。来自referencesource.microsoft.com:
过去,当InternalAssemblyBuilder是AssemblyBuilder时,不受信任的用户可以将Assembly向下转换为AssemblyBuilder,并使用最初通过DefineDynamicAssembly创建AssemblyBuilder的受信任代码的提升权限发出代码。如今,这种情况不再发生,因为通过 AssemblyGetAssemblies() 返回的程序集将是一个 InternalAssemblyBuilder。
或者,您可以反映动态程序集中的类型,并使用命名空间中的 a 和其他帮助程序来重建它们,但这一切似乎有点乏味。new AssemblyBuilderSystem.Reflection.Emit
总而言之,按照当前的实现方式,您将在试图将fsi生成的类型公开给其他域的流中游泳。
| 归档时间: |
|
| 查看次数: |
151 次 |
| 最近记录: |