Пользовательский интерфейс Windows (UWP или 8.1) в интерактивном F #

Ссылаясь на библиотеки DLL WPF по умолчанию, довольно легко делать все, что вы могли бы сделать, используя WPF только для кода:

#r "PresentationCore.dll"
#r "PresentationFramework.dll"
// ...other DLLs...
#r "WindowsBase.dll"

let window = System.Windows.Window()
let panel = System.Windows.Controls.StackPanel()
let button = System.Windows.Controls.Button()
panel.Children.Add button
button.Content <- "hi"

window.Content <- panel

window.Show()

... и вы можете манипулировать им, пока окно все еще открыто ...

button.Click.Add (fun _ ->
    button.Content <-
        button.Content :?> string |> fun x -> (x + "!") :> obj)

... а затем нажмите кнопку, чтобы увидеть, как это работает. Это кажется довольно мощным способом создания компонентов пользовательского интерфейса.

Есть ли способ сделать то же самое с пространством имен / элементами управления / инфраструктурой пользовательского интерфейса Windows.UI - загрузить некоторые сборки в интерактивном F # и создать экземпляры компонентов пользовательского интерфейса на лету?

Я наивно пытался сослаться на файлы, которые казались актуальными:

#r @"C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\2.0.0.0\Windows.Foundation.UniversalApiContract.winmd"
#r @"C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\2.0.0.0\Windows.Foundation.FoundationContract.winmd"

... и это дает мне intellisense в пространствах имен Windows.UI. Но когда я пытаюсь создать что-то:

Windows.UI.Xaml.Application()

Я получил:

error FS0193: Could not load file or assembly 'file:///C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\2.0.0.0\Windows.Foundation.UniversalApiContract.winmd' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)


person Overlord Zurg    schedule 13.07.2016    source источник


Ответы (2)


Компилятор не поддерживает сборки WinRT, поэтому вы не сможете ссылаться на сборку, как вы пытаетесь это сделать, и аккуратно использовать в них типы.

С другой стороны ... поскольку среда выполнения .NET имеет встроенную поддержку типов WinRT, вы можете использовать отражение для загрузки этих типов и доступа к их членам. Приложив много усилий, вы даже можете создать провайдер типов, чтобы создать чистый фасад над этим отражением и создать впечатление, будто вы можете использовать типы напрямую. Вот небольшой пример того, как напрямую вызвать WinRT API из F # через отражение:

open System.Reflection

let (?) (o:obj) s : 'a =
    let rec build ty args =
        if Reflection.FSharpType.IsFunction ty then
            let dom, rng = Reflection.FSharpType.GetFunctionElements ty
            let mkArgs =
                if dom = typeof<unit> then
                    if Reflection.FSharpType.IsFunction rng then failwith "Unit as non-final argument in curried definition?"
                    fun _ -> args
                else
                    fun arg -> arg::args
            Reflection.FSharpValue.MakeFunction(ty, fun o -> build rng (mkArgs o))
        else
            let rcvr,ty,flags =
                match o with
                | :? System.Type as ty -> null,ty,BindingFlags.Static
                | _ -> o,o.GetType(),BindingFlags.Instance
            let flags = flags ||| BindingFlags.Public
            let meth =
                if Reflection.FSharpType.IsFunction typeof<'a> then
                    query {
                        for m in ty.GetMethods(flags) do
                        where (m.Name = s)
                        where (m.GetParameters().Length = args.Length)
                        exactlyOne
                    }                    
                else
                    ty.GetProperty(s, flags).GetGetMethod()
            meth.Invoke(rcvr, args |> List.toArray)

    build typeof<'a> [] :?> 'a

let Clipboard = System.Type.GetType(@"Windows.ApplicationModel.DataTransfer.Clipboard, Windows.ApplicationModel, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime")

Clipboard?GetContent()?AvailableFormats |> Seq.iter (printfn "%s")
person kvb    schedule 13.07.2016
comment
Что означает отсутствие поддержки компилятором сборок WinRT? Компилятор F # не может загружать сборки из .winmd файлов? winmd означает, что это сборка WinRT? - person Overlord Zurg; 13.07.2016
comment
Да, я имею в виду, что компилятор ничего не знает о сборках .winmd, которые содержат компоненты среды выполнения Windows и не являются стандартными сборками .NET, хотя они близки (например, они содержат только метаданные, но не реализованы). - person kvb; 13.07.2016

Насколько я понимаю, для UWP пока нет поддержки F #.
См., Например, эту свежую открытую проблему.

person weismat    schedule 13.07.2016
comment
Вопрос закрыт. - person Rei Miyasaka; 04.04.2018