From eba083ee046857b7645189f87da303c0ea97fcd8 Mon Sep 17 00:00:00 2001 From: Brian Lagunas Date: Tue, 21 Apr 2020 11:23:06 -0600 Subject: [PATCH] Added new PrismBootstrapper API --- e2e/Wpf/HelloWorld.Bootstraper/App.xaml | 7 + e2e/Wpf/HelloWorld.Bootstraper/App.xaml.cs | 18 ++ .../HelloWorld.Bootstraper/Bootstrapper.cs | 21 ++ .../HelloWorld.Bootstrapper.csproj | 16 ++ .../ViewModels/MainWindowViewModel.cs | 16 ++ .../Views/MainWindow.xaml | 9 + .../Views/MainWindow.xaml.cs | 15 ++ e2e/Wpf/HelloWorld.sln | 10 +- src/Wpf/Prism.DryIoc.Wpf/PrismBootstrapper.cs | 27 +++ src/Wpf/Prism.Unity.Wpf/PrismBootstrapper.cs | 19 ++ src/Wpf/Prism.Wpf/PrismBootstrapperBase.cs | 216 ++++++++++++++++++ 11 files changed, 372 insertions(+), 2 deletions(-) create mode 100644 e2e/Wpf/HelloWorld.Bootstraper/App.xaml create mode 100644 e2e/Wpf/HelloWorld.Bootstraper/App.xaml.cs create mode 100644 e2e/Wpf/HelloWorld.Bootstraper/Bootstrapper.cs create mode 100644 e2e/Wpf/HelloWorld.Bootstraper/HelloWorld.Bootstrapper.csproj create mode 100644 e2e/Wpf/HelloWorld.Bootstraper/ViewModels/MainWindowViewModel.cs create mode 100644 e2e/Wpf/HelloWorld.Bootstraper/Views/MainWindow.xaml create mode 100644 e2e/Wpf/HelloWorld.Bootstraper/Views/MainWindow.xaml.cs create mode 100644 src/Wpf/Prism.DryIoc.Wpf/PrismBootstrapper.cs create mode 100644 src/Wpf/Prism.Unity.Wpf/PrismBootstrapper.cs create mode 100644 src/Wpf/Prism.Wpf/PrismBootstrapperBase.cs diff --git a/e2e/Wpf/HelloWorld.Bootstraper/App.xaml b/e2e/Wpf/HelloWorld.Bootstraper/App.xaml new file mode 100644 index 00000000..df462fee --- /dev/null +++ b/e2e/Wpf/HelloWorld.Bootstraper/App.xaml @@ -0,0 +1,7 @@ + + + + + diff --git a/e2e/Wpf/HelloWorld.Bootstraper/App.xaml.cs b/e2e/Wpf/HelloWorld.Bootstraper/App.xaml.cs new file mode 100644 index 00000000..297f93d3 --- /dev/null +++ b/e2e/Wpf/HelloWorld.Bootstraper/App.xaml.cs @@ -0,0 +1,18 @@ +using System.Windows; + +namespace HelloWorld +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + protected override void OnStartup(StartupEventArgs e) + { + base.OnStartup(e); + + var bs = new Bootstrapper(); + bs.Run(); + } + } +} diff --git a/e2e/Wpf/HelloWorld.Bootstraper/Bootstrapper.cs b/e2e/Wpf/HelloWorld.Bootstraper/Bootstrapper.cs new file mode 100644 index 00000000..d4910e60 --- /dev/null +++ b/e2e/Wpf/HelloWorld.Bootstraper/Bootstrapper.cs @@ -0,0 +1,21 @@ +using HelloWorld.Views; +using Prism.Ioc; +using Prism.Unity; +using System.Windows; +using Unity; + +namespace HelloWorld +{ + class Bootstrapper : PrismBootstrapper + { + protected override Window CreateShell() + { + return Container.Resolve(); + } + + protected override void RegisterTypes(IContainerRegistry containerRegistry) + { + + } + } +} \ No newline at end of file diff --git a/e2e/Wpf/HelloWorld.Bootstraper/HelloWorld.Bootstrapper.csproj b/e2e/Wpf/HelloWorld.Bootstraper/HelloWorld.Bootstrapper.csproj new file mode 100644 index 00000000..3c611728 --- /dev/null +++ b/e2e/Wpf/HelloWorld.Bootstraper/HelloWorld.Bootstrapper.csproj @@ -0,0 +1,16 @@ + + + + WinExe + netcoreapp3.1 + true + HelloWorld + + + + + + + + + \ No newline at end of file diff --git a/e2e/Wpf/HelloWorld.Bootstraper/ViewModels/MainWindowViewModel.cs b/e2e/Wpf/HelloWorld.Bootstraper/ViewModels/MainWindowViewModel.cs new file mode 100644 index 00000000..36703653 --- /dev/null +++ b/e2e/Wpf/HelloWorld.Bootstraper/ViewModels/MainWindowViewModel.cs @@ -0,0 +1,16 @@ +using Prism.Commands; +using Prism.Mvvm; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace HelloWorld.ViewModels +{ + public class MainWindowViewModel : BindableBase + { + public MainWindowViewModel() + { + + } + } +} diff --git a/e2e/Wpf/HelloWorld.Bootstraper/Views/MainWindow.xaml b/e2e/Wpf/HelloWorld.Bootstraper/Views/MainWindow.xaml new file mode 100644 index 00000000..fdb4280e --- /dev/null +++ b/e2e/Wpf/HelloWorld.Bootstraper/Views/MainWindow.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/e2e/Wpf/HelloWorld.Bootstraper/Views/MainWindow.xaml.cs b/e2e/Wpf/HelloWorld.Bootstraper/Views/MainWindow.xaml.cs new file mode 100644 index 00000000..8c68cab4 --- /dev/null +++ b/e2e/Wpf/HelloWorld.Bootstraper/Views/MainWindow.xaml.cs @@ -0,0 +1,15 @@ +using System.Windows; + +namespace HelloWorld.Views +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + } + } +} diff --git a/e2e/Wpf/HelloWorld.sln b/e2e/Wpf/HelloWorld.sln index e1190864..0dec76be 100644 --- a/e2e/Wpf/HelloWorld.sln +++ b/e2e/Wpf/HelloWorld.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld", "HelloWorld\HelloWorld.csproj", "{B03C14CC-8DE9-40EE-9562-12B976E4CEE8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloWorld", "HelloWorld\HelloWorld.csproj", "{B03C14CC-8DE9-40EE-9562-12B976E4CEE8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prism", "..\..\src\Prism.Core\Prism.Core.csproj", "{457AA668-72BB-4701-9A4E-FA86B0C412DE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prism.Core", "..\..\src\Prism.Core\Prism.Core.csproj", "{457AA668-72BB-4701-9A4E-FA86B0C412DE}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Prism Library", "Prism Library", "{15CF1FE1-D78E-4E3D-A9F8-FA0FCC56A83A}" EndProject @@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prism.DryIoc.Wpf", "..\..\s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prism.Unity.Wpf", "..\..\src\Wpf\Prism.Unity.Wpf\Prism.Unity.Wpf.csproj", "{DEBADAAB-5C78-444E-AA77-336A43B49EC3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld.Bootstrapper", "HelloWorld.Bootstraper\HelloWorld.Bootstrapper.csproj", "{36C11381-D25A-4E40-956F-05E9C440FA86}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -41,6 +43,10 @@ Global {DEBADAAB-5C78-444E-AA77-336A43B49EC3}.Debug|Any CPU.Build.0 = Debug|Any CPU {DEBADAAB-5C78-444E-AA77-336A43B49EC3}.Release|Any CPU.ActiveCfg = Release|Any CPU {DEBADAAB-5C78-444E-AA77-336A43B49EC3}.Release|Any CPU.Build.0 = Release|Any CPU + {36C11381-D25A-4E40-956F-05E9C440FA86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36C11381-D25A-4E40-956F-05E9C440FA86}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36C11381-D25A-4E40-956F-05E9C440FA86}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36C11381-D25A-4E40-956F-05E9C440FA86}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Wpf/Prism.DryIoc.Wpf/PrismBootstrapper.cs b/src/Wpf/Prism.DryIoc.Wpf/PrismBootstrapper.cs new file mode 100644 index 00000000..8e17a86d --- /dev/null +++ b/src/Wpf/Prism.DryIoc.Wpf/PrismBootstrapper.cs @@ -0,0 +1,27 @@ +using DryIoc; +using Prism.Ioc; +using System; + +namespace Prism.DryIoc +{ + public abstract class PrismBootstrapper : PrismBootstrapperBase + { + /// + /// Create to alter behavior of + /// + /// An instance of + protected virtual Rules CreateContainerRules() => Rules.Default.WithAutoConcreteTypeResolution() + .With(Made.Of(FactoryMethod.ConstructorWithResolvableArguments)) + .WithDefaultIfAlreadyRegistered(IfAlreadyRegistered.Replace); + + protected override IContainerExtension CreateContainerExtension() + { + return new DryIocContainerExtension(new Container(CreateContainerRules())); + } + + protected override void RegisterFrameworkExceptionTypes() + { + ExceptionExtensions.RegisterFrameworkExceptionType(typeof(ContainerException)); + } + } +} diff --git a/src/Wpf/Prism.Unity.Wpf/PrismBootstrapper.cs b/src/Wpf/Prism.Unity.Wpf/PrismBootstrapper.cs new file mode 100644 index 00000000..817bd32e --- /dev/null +++ b/src/Wpf/Prism.Unity.Wpf/PrismBootstrapper.cs @@ -0,0 +1,19 @@ +using Prism.Ioc; +using System; +using Unity; + +namespace Prism.Unity +{ + public abstract class PrismBootstrapper : PrismBootstrapperBase + { + protected override IContainerExtension CreateContainerExtension() + { + return new UnityContainerExtension(); + } + + protected override void RegisterFrameworkExceptionTypes() + { + ExceptionExtensions.RegisterFrameworkExceptionType(typeof(ResolutionFailedException)); + } + } +} diff --git a/src/Wpf/Prism.Wpf/PrismBootstrapperBase.cs b/src/Wpf/Prism.Wpf/PrismBootstrapperBase.cs new file mode 100644 index 00000000..feeaca55 --- /dev/null +++ b/src/Wpf/Prism.Wpf/PrismBootstrapperBase.cs @@ -0,0 +1,216 @@ +using Prism.Events; +using Prism.Ioc; +using Prism.Logging; +using Prism.Modularity; +using Prism.Mvvm; +using Prism.Regions; +using Prism.Regions.Behaviors; +using Prism.Services.Dialogs; +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; + +namespace Prism +{ + public abstract class PrismBootstrapperBase + { + IContainerExtension _containerExtension; + IModuleCatalog _moduleCatalog; + + /// + /// The dependency injection container used to resolve objects + /// + public IContainerProvider Container => _containerExtension; + + /// + /// Gets the shell user interface + /// + /// The shell user interface. + protected Window Shell { get; set; } + + + public void Run() + { + InitializeInternal(); + } + + /// + /// Run the initialization process. + /// + void InitializeInternal() + { + ConfigureViewModelLocator(); + Initialize(); + OnInitialized(); + } + + /// + /// Configures the used by Prism. + /// + protected virtual void ConfigureViewModelLocator() + { + ViewModelLocationProvider.SetDefaultViewModelFactory((view, type) => + { + return Container.Resolve(type); + }); + } + + /// + /// Runs the initialization sequence to configure the Prism application. + /// + public virtual void Initialize() + { + ContainerLocator.SetContainerExtension(CreateContainerExtension); + _containerExtension = ContainerLocator.Current; + _moduleCatalog = CreateModuleCatalog(); + RegisterRequiredTypes(_containerExtension); + RegisterTypes(_containerExtension); + _containerExtension.FinalizeExtension(); + + ConfigureModuleCatalog(_moduleCatalog); + + var regionAdapterMappins = _containerExtension.Resolve(); + ConfigureRegionAdapterMappings(regionAdapterMappins); + + var defaultRegionBehaviors = _containerExtension.Resolve(); + ConfigureDefaultRegionBehaviors(defaultRegionBehaviors); + + RegisterFrameworkExceptionTypes(); + + var shell = CreateShell(); + if (shell != null) + { + RegionManager.SetRegionManager(shell, _containerExtension.Resolve()); + RegionManager.UpdateRegions(); + InitializeShell(shell); + } + + InitializeModules(); + } + + /// + /// Creates the container used by Prism. + /// + /// The container + protected abstract IContainerExtension CreateContainerExtension(); + + /// + /// Creates the used by Prism. + /// + /// + /// The base implementation returns a new ModuleCatalog. + /// + protected virtual IModuleCatalog CreateModuleCatalog() + { + return new ModuleCatalog(); + } + + /// + /// Registers all types that are required by Prism to function with the container. + /// + /// + protected virtual void RegisterRequiredTypes(IContainerRegistry containerRegistry) + { + containerRegistry.RegisterInstance(_moduleCatalog); + containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); + containerRegistry.Register(); + containerRegistry.Register(); + containerRegistry.Register(); + containerRegistry.Register(); //default dialog host + } + + /// + /// Used to register types with the container that will be used by your application. + /// + protected abstract void RegisterTypes(IContainerRegistry containerRegistry); + + /// + /// Configures the . + /// This will be the list of default behaviors that will be added to a region. + /// + protected virtual void ConfigureDefaultRegionBehaviors(IRegionBehaviorFactory regionBehaviors) + { + if (regionBehaviors != null) + { + regionBehaviors.AddIfMissing(BindRegionContextToDependencyObjectBehavior.BehaviorKey, typeof(BindRegionContextToDependencyObjectBehavior)); + regionBehaviors.AddIfMissing(RegionActiveAwareBehavior.BehaviorKey, typeof(RegionActiveAwareBehavior)); + regionBehaviors.AddIfMissing(SyncRegionContextWithHostBehavior.BehaviorKey, typeof(SyncRegionContextWithHostBehavior)); + regionBehaviors.AddIfMissing(RegionManagerRegistrationBehavior.BehaviorKey, typeof(RegionManagerRegistrationBehavior)); + regionBehaviors.AddIfMissing(RegionMemberLifetimeBehavior.BehaviorKey, typeof(RegionMemberLifetimeBehavior)); + regionBehaviors.AddIfMissing(ClearChildViewsRegionBehavior.BehaviorKey, typeof(ClearChildViewsRegionBehavior)); + regionBehaviors.AddIfMissing(AutoPopulateRegionBehavior.BehaviorKey, typeof(AutoPopulateRegionBehavior)); + regionBehaviors.AddIfMissing(IDestructibleRegionBehavior.BehaviorKey, typeof(IDestructibleRegionBehavior)); + } + } + + /// + /// Configures the default region adapter mappings to use in the application, in order + /// to adapt UI controls defined in XAML to use a region and register it automatically. + /// May be overwritten in a derived class to add specific mappings required by the application. + /// + /// The instance containing all the mappings. + protected virtual void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings) + { + if (regionAdapterMappings != null) + { + regionAdapterMappings.RegisterMapping(typeof(Selector), _containerExtension.Resolve()); + regionAdapterMappings.RegisterMapping(typeof(ItemsControl), _containerExtension.Resolve()); + regionAdapterMappings.RegisterMapping(typeof(ContentControl), _containerExtension.Resolve()); + } + } + + /// + /// Registers the s of the Exceptions that are not considered + /// root exceptions by the . + /// + protected virtual void RegisterFrameworkExceptionTypes() + { + } + + /// + /// Creates the shell or main window of the application. + /// + /// The shell of the application. + protected abstract Window CreateShell(); + + /// + /// Initializes the shell. + /// + protected virtual void InitializeShell(Window shell) + { + Shell = shell; + } + + /// + /// Contains actions that should occur last. + /// + protected virtual void OnInitialized() + { + Shell?.Show(); + } + + /// + /// Configures the used by Prism. + /// + protected virtual void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) { } + + /// + /// Initializes the modules. + /// + protected virtual void InitializeModules() + { + IModuleManager manager = _containerExtension.Resolve(); + manager.Run(); + } + } +}