I have a WPF application which uses Caliburn.Micro and provides a frame for different types of shells. All these shells are implementing the interface IShell
.
As an example lets take a main window which acts as the host and a tabcontrol to host the different loaded shells, one tab for each shell. Each shell can be closed by closing the tab.
Currently it's uses MEF for IOC support, composition (with attributes) and it's child container.
A shell is opened on user action: He selects a file where plugin information and other data are stored.
Based on this file data and some fixed types (like reporting) a shell is created and hosted in the frame.
All components which are located in the plugin assemblies and some other framework components should be scoped to the shell, some other will be components from the frame.
When the user closes a tap the dynamically created scope can be disposed.
Since the frame is currently responsible for creating the plugin shell components and needs to add these views/viewmodels to the frame infrastructure
The caliburn bootstrapper for the frame looks like this
protected override void Configure()
{
// register host assembly
AssemblyScanner.AddAssembly(typeof(AppBootstrapper).Assembly);
m_container = new Container();
container.RegisterSingle<IWindowManager, WindowManager>();
container.RegisterSingle<IEventAggregator, EventAggregator>();
container.RegisterSingle<IShellFactory, ShellFactory>();
// view and viewmodel registrations for the shell
// scan binaries folder for all implementations of IShell
var shells = AssemblyScanner.ScanForType<IShell>();
// register them as a collection and lifetimescoped
foreach (var shell in shells)
{
m_container.Register(shell, shell, new LifetimeScopeLifestyle());
}
m_container.RegisterAll<IShell>(shells);
m_container.Verify();
}
The factory for creating the shells
public IEnumerable<IShell> GetAll()
{
using (m_container.BeginLifetimeScope())
{
var instances = m_container.GetAllInstances<IShell>();
return instances;
}
}
In the frame main viewmodel the factory is called
protected override void OnInitialize()
{
var shells = m_factory.GetAll();
Items.AddRange(shells);
}
The plugins specify their needed registrations which will be lifetimescoped too.
The call var shells = m_factory.GetAll();
fails with the exception that a scoped service is requested outside of a scope which makes sense.
After reading the docs and samples I am not sure how to build that with SimpleInjector.
Creating and manageing child containers seems the wrong way with SimpleInjector. Now I have the feeling that I miss something.
Update
Yes the user is able to switch tabs, can close a tab, looks a lot like VisualStudio so no modal windows are possible.
The user chooses a file on a screen which is loaded. Next all plugin informations are collected and merged with the plaform plugins. Now I have a bunch of types (viewmodels, service, ...) from which the tab content is build.