Создание нового домена приложения в F # Interactive - PullRequest
0 голосов
/ 15 мая 2018

Мне нужна возможность создавать новый домен приложений в F # интерактивный для размещения нескольких приложений 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 #?

1 Ответ

0 голосов
/ 17 мая 2018

Вступление из документов :

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

Как правило, сначала необходимо сохранить диск, ref примечания - Ограничения на передачу в удаленные домены приложений :

В некоторых сценариях требуется, чтобы динамическая сборка создавалась и выполнялась в удаленном домене приложения. Reflection emit не позволяет динамической сборке быть отправленной непосредственно в удаленный домен приложения. Решение состоит в том, чтобы создать динамическую сборку в текущем домене приложения, сохранить созданную динамическую сборку на диск и затем загрузить динамическую сборку в удаленный домен приложения.

При успешном приведении динамической сборки к AssemblyBuilder будет открыт метод Save. К сожалению, этот рабочий процесс также был отключен.

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

Броски

System.InvalidCastException: невозможно преобразовать объект типа «System.Reflection.Emit.InternalAssemblyBuilder» в тип «System.Reflection.Emit.AssemblyBuilder '

Мы имеем дело с внутренним типом, очевидно, мы не собираемся пачкать руки. От referenceource.microsoft.com :

В прошлом, когда InternalAssemblyBuilder был AssemblyBuilder, ненадежный пользователь мог преобразовывать Assembly в AssemblyBuilder и выдавать код с повышенными разрешениями доверенного кода, который первоначально создавал AssemblyBuilder через DefineDynamicAssembly. Сегодня этого больше не может быть, потому что сборка, возвращаемая с помощью AssemblyGetAssemblies (), будет InternalAssemblyBuilder.

Кроме того, вы можете поразмышлять над типами в динамической сборке и восстановить их , используя new AssemblyBuilder и другие помощники в пространстве имен System.Reflection.Emit, но все это выглядит немного утомительно.

В заключение, как он реализован в настоящее время, вы будете плыть против потока, пытаясь открыть сгенерированные типы fsi для других доменов.

...