Windows UI (UWP 或 8.1) 在 F# 交互环境中

5

通过引用默认的WPF DLL,使用代码实现 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)

...然后点击按钮查看它的工作原理。这似乎是一种构建UI组件的非常强大的方式。

在Windows.UI命名空间/控件/UI框架中是否有类似的方法 - 在F#交互中加载一些程序集并动态实例化UI组件?

我尝试了一些看起来相关的文件,但都很幼稚:

#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"

我使用这种方式可以让我在Windows.UI命名空间中获得智能感知。但是当我尝试实例化某些东西时:

Windows.UI.Xaml.Application()

我得到了以下错误信息:error FS0193:无法加载文件或程序集“file:///C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\2.0.0.0\Windows.Foundation.UniversalApiContract.winmd”,或其某个依赖项。 操作不受支持。 (来自 HRESULT 的异常:0x80131515)
2个回答

3

据我了解,目前还没有针对UWP的F#支持。
例如,可以看到这个最新的问题


问题现已关闭。 - Rei Miyasaka

3

WinRT程序集不支持编译器,因此您无法像尝试的那样引用程序集并干净地使用其中的类型。

另一方面...由于.NET运行时具有对WinRT类型的本机支持,您可以使用反射来加载这些类型并访问它们的成员。通过大量努力,您甚至可以构建一个类型提供程序,以在反射上提供一个干净的外观,并使其看起来好像可以直接使用这些类型。以下是一个小例子,展示了如何通过反射从F#直接调用WinRT API:

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")

“no compiler support for WinRT assemblies” 是什么意思?F# 编译器无法加载 .winmd 文件中的程序集吗?winmd 是否意味着它是一个 WinRT 程序集? - Overlord Zurg
2
是的,我的意思是编译器不知道包含“Windows Runtime”组件的.winmd程序集,它们并不完全是标准的.NET程序集,尽管它们很接近(例如,它们仅包含元数据,但没有实现)。 - kvb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接