Unity和类型提供者

时间:2012-08-19 09:40:11

标签: wpf f# prism type-providers

运行以下代码后,在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#中的这种差异编译/运行时非常令人惊讶。虽然必须有充分的理由,但我忘记了发生这种情况的可能性!

1 个答案:

答案 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