运行以下代码后,在F#WPF模板的项目中添加了Nuget Prism
module MainApp
open System
open System.Windows
open System.Windows.Controls
open Microsoft.Practices.Unity
open Microsoft.Practices.Prism.UnityExtensions;
open FSharpx
type Shell = XAML<"MainWindow.xaml">
type App () =
inherit Application()
override x.OnStartup e =
base.OnStartup(e);
let bt = new BootStrapper()
bt.Run()
and BootStrapper () =
inherit UnityBootstrapper()
override x.CreateShell() =
let a = x.Container.Resolve<Shell>()
let b = a.Root
b :> DependencyObject
override x.InitializeShell()=
base.InitializeShell();
App.Current.MainWindow <- x.Shell :?> Window
App.Current.MainWindow.Show()
[<STAThread>]
(new App()).Run() |> ignore
我在编译时没有收到任何错误,但是在运行时,一个异常说a.Root是一个FrameworkElement,它不能被转换为Window。
在调试时,我看到'a'的运行时内容与XAML Type提供程序的内部表示形式相同,{FSharpx.TypeProviders.XamlProvider.XamlFile},如here中所示,它的内部字典是空的。
我不确定TP的内部表示是否应该浮出水面。 看起来好像Unity忽略了Type Provider机制。 我想这是因为Unity似乎使用反射来计算依赖性。
有没有人使用TP可能会有类似的行为,可以解决一些问题?
PS:F#中的这种差异编译/运行时非常令人惊讶。虽然必须有充分的理由,但我忘记了发生这种情况的可能性!
答案 0 :(得分:3)
正如我在FSharpX源代码中看到的那样,Xaml类型提供程序被删除了 - 你没有像元数据那样的Shell类型,所有使用这种类型的东西都被删除到基类型的操作 - XamlFile。所以这个
let a = x.Container.Resolve<Shell>()
会像
一样被删除let a = x.Container.Resolve<XamlFile>()
所以Unity将只创建XamlFile的新实例。相反,如果您尝试直接实例化Shell - 那么F#编译器将使用提供的构造函数,所以这个
let a = Shell()
实际上意味着
let a = XamlFile(XamlReader.Parse( <content-of-xaml-file> ))
在您的情况下,您可以实例化Shell,然后使用x.Container.BuildUp()填充其内部。
type App () =
inherit Application()
override x.OnStartup e =
base.OnStartup(e);
let bt = new BootStrapper()
bt.Run()
and BootStrapper () =
inherit UnityBootstrapper()
override x.CreateShell() =
let a = Shell()
x.Container.BuildUp(a.Root) :> _
override x.InitializeShell()=
base.InitializeShell();
App.Current.MainWindow <- x.Shell :?> Window
App.Current.MainWindow.Show()
[<STAThread>]
(new App()).Run() |> ignore