Add StyletIoCBootstrapper between Bootstrapper<T> and BootstrapperBase

This covers the case where there's no root ViewModel
This commit is contained in:
mwdpb 2021-02-03 14:12:45 -05:00 committed by Antony Male
parent 8974f8ad36
commit d228af4ccc
2 changed files with 101 additions and 69 deletions

View File

@ -8,14 +8,12 @@ namespace Stylet
/// <summary>
/// Bootstrapper to be extended by any application which wants to use StyletIoC (the default)
/// </summary>
/// <remarks>
/// If you don't have a root ViewModel, you might prefer to override <see cref="StyletIoCBootstrapper"/>
/// </remarks>
/// <typeparam name="TRootViewModel">Type of the root ViewModel. This will be instantiated and displayed</typeparam>
public abstract class Bootstrapper<TRootViewModel> : BootstrapperBase where TRootViewModel : class
public abstract class Bootstrapper<TRootViewModel> : StyletIoCBootstrapper where TRootViewModel : class
{
/// <summary>
/// Gets or sets the Bootstrapper's IoC container. This is created after ConfigureIoC has been run.
/// </summary>
protected IContainer Container { get; set; }
private TRootViewModel _rootViewModel;
/// <summary>
@ -25,65 +23,7 @@ namespace Stylet
{
get { return this._rootViewModel ?? (this._rootViewModel = this.Container.Get<TRootViewModel>()); }
}
/// <summary>
/// Overridden from BootstrapperBase, this sets up the IoC container
/// </summary>
protected override sealed void ConfigureBootstrapper()
{
var builder = new StyletIoCBuilder();
builder.Assemblies = new List<Assembly>(new List<Assembly>() { this.GetType().Assembly });
// Call DefaultConfigureIoC *after* ConfigureIoIC, so that they can customize builder.Assemblies
this.ConfigureIoC(builder);
this.DefaultConfigureIoC(builder);
this.Container = builder.BuildContainer();
}
/// <summary>
/// Carries out default configuration of StyletIoC. Override if you don't want to do this
/// </summary>
/// <param name="builder">StyletIoC builder to use to configure the container</param>
protected virtual void DefaultConfigureIoC(StyletIoCBuilder builder)
{
// Mark these as weak-bindings, so the user can replace them if they want
var viewManagerConfig = new ViewManagerConfig()
{
ViewFactory = this.GetInstance,
ViewAssemblies = new List<Assembly>() { this.GetType().Assembly }
};
builder.Bind<ViewManagerConfig>().ToInstance(viewManagerConfig).AsWeakBinding();
// Bind it to both IViewManager and to itself, so that people can get it with Container.Get<ViewManager>()
builder.Bind<IViewManager>().And<ViewManager>().To<ViewManager>().InSingletonScope().AsWeakBinding();
builder.Bind<IWindowManagerConfig>().ToInstance(this).DisposeWithContainer(false).AsWeakBinding();
builder.Bind<IWindowManager>().To<WindowManager>().InSingletonScope().AsWeakBinding();
builder.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope().AsWeakBinding();
builder.Bind<IMessageBoxViewModel>().To<MessageBoxViewModel>().AsWeakBinding();
// Stylet's assembly isn't added to the container, so add this explicitly
builder.Bind<MessageBoxView>().ToSelf();
builder.Autobind();
}
/// <summary>
/// Override to add your own types to the IoC container.
/// </summary>
/// <param name="builder">StyletIoC builder to use to configure the container</param>
protected virtual void ConfigureIoC(IStyletIoCBuilder builder) { }
/// <summary>
/// Given a type, use the IoC container to fetch an instance of it
/// </summary>
/// <param name="type">Type to fetch</param>
/// <returns>Fetched instance</returns>
public override object GetInstance(Type type)
{
return this.Container.Get(type);
}
/// <summary>
/// Called when the application is launched. Displays the root view.
/// </summary>
@ -97,12 +37,11 @@ namespace Stylet
/// </summary>
public override void Dispose()
{
// Dispose the container last
base.Dispose();
// Don't create the root ViewModel if it doesn't already exist...
ScreenExtensions.TryDispose(this._rootViewModel);
if (this.Container != null)
this.Container.Dispose();
// Dispose the container last
base.Dispose();
}
}
}

View File

@ -0,0 +1,93 @@
using StyletIoC;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Stylet
{
/// <summary>
/// Bootstrapper to be extended by any application which wants to use StyletIoC, but doesn't have a root ViewModel
/// </summary>
/// <remarks>
/// You would normally use <see cref="Bootstrapper{TRootViewModel}"/>, which lets you specify the root ViewModel
/// to display. If you don't want to show a window on startup, override <see cref="BootstrapperBase.Launch"/>
/// but don't call <see cref="BootstrapperBase.DisplayRootView(object)"/>.
/// </remarks>
public abstract class StyletIoCBootstrapper : BootstrapperBase
{
/// <summary>
/// Gets or sets the Bootstrapper's IoC container. This is created after ConfigureIoC has been run.
/// </summary>
protected IContainer Container { get; set; }
/// <summary>
/// Overridden from BootstrapperBase, this sets up the IoC container
/// </summary>
protected override sealed void ConfigureBootstrapper()
{
var builder = new StyletIoCBuilder();
builder.Assemblies = new List<Assembly>(new List<Assembly>() { this.GetType().Assembly });
// Call DefaultConfigureIoC *after* ConfigureIoIC, so that they can customize builder.Assemblies
this.ConfigureIoC(builder);
this.DefaultConfigureIoC(builder);
this.Container = builder.BuildContainer();
}
/// <summary>
/// Carries out default configuration of StyletIoC. Override if you don't want to do this
/// </summary>
/// <param name="builder">StyletIoC builder to use to configure the container</param>
protected virtual void DefaultConfigureIoC(StyletIoCBuilder builder)
{
// Mark these as weak-bindings, so the user can replace them if they want
var viewManagerConfig = new ViewManagerConfig()
{
ViewFactory = this.GetInstance,
ViewAssemblies = new List<Assembly>() { this.GetType().Assembly }
};
builder.Bind<ViewManagerConfig>().ToInstance(viewManagerConfig).AsWeakBinding();
// Bind it to both IViewManager and to itself, so that people can get it with Container.Get<ViewManager>()
builder.Bind<IViewManager>().And<ViewManager>().To<ViewManager>().InSingletonScope().AsWeakBinding();
builder.Bind<IWindowManagerConfig>().ToInstance(this).DisposeWithContainer(false).AsWeakBinding();
builder.Bind<IWindowManager>().To<WindowManager>().InSingletonScope().AsWeakBinding();
builder.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope().AsWeakBinding();
builder.Bind<IMessageBoxViewModel>().To<MessageBoxViewModel>().AsWeakBinding();
// Stylet's assembly isn't added to the container, so add this explicitly
builder.Bind<MessageBoxView>().ToSelf();
builder.Autobind();
}
/// <summary>
/// Override to add your own types to the IoC container.
/// </summary>
/// <param name="builder">StyletIoC builder to use to configure the container</param>
protected virtual void ConfigureIoC(IStyletIoCBuilder builder) { }
/// <summary>
/// Given a type, use the IoC container to fetch an instance of it
/// </summary>
/// <param name="type">Type to fetch</param>
/// <returns>Fetched instance</returns>
public override object GetInstance(Type type)
{
return this.Container.Get(type);
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public override void Dispose()
{
base.Dispose();
// Dispose the container last
if (this.Container != null)
this.Container.Dispose();
}
}
}