Upon running the following code, in a project from F# WPF template, to which is added the 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
I get no error at compile time, but at runtime an exception says that a.Root is a FrameworkElement, which can not be casted to a Window.
Upon debugging, I see that the runtime content of 'a' is of same type than the internal representation of the XAML Type provider, a {FSharpx.TypeProviders.XamlProvider.XamlFile}, as in here, and its internal dictionary is empty.
I am not sure the internal representation of the TP is supposed to surface out. It looks as if the Type Provider mechanic is ignored by Unity. I suppose it is because Unity seems to work with reflection to figure out dependencies.
Has anyone experienced a similar behaviour using TP that could shed some light ?
PS :This discrepency compile/runtime in F# is quite suprising. Although there must be a good reason for it I had forgotten the possibility of such occurences !
As I see in FSharpX source code, Xaml type provider is erased one - you don't have Shell type as is in metadata, everything that works with this type is erased to operations with base type - XamlFile. So this
let a = x.Container.Resolve<Shell>()
will be erased to smth like
let a = x.Container.Resolve<XamlFile>()
so Unity will just create fresh instance of XamlFile. In contrast, if you try to instantiate Shell directly - then F# compiler will use provided constructors so this
let a = Shell()
will effectively mean
let a = XamlFile(XamlReader.Parse( <content-of-xaml-file> ))
In your case you can probably instantiate Shell and then use x.Container.BuildUp() to populate its internals.
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