How to keep the Shell configurable with PRISM 4.1 & Unity?

671 views Asked by At

I am writing a WPF application using PRISM 4.1 & Unity. The application will have every UI component configurable, including the Shell itself!

E.g. I have an interface called IShell. Consumers of the app can have their own implementation of IShell if they are not satisfied with my default implementation which has Regions and Views defined in some fixed way.

Now from my Bootstrapper class (which inherits UnityBootstrapper), I want to know the type registered for IShell with the Unity container. The overriden CreateShell will return configured type of the IShell.

My App.config looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity>
    <container>
        <register type="Interfaces.IShell, Interfaces" mapTo="PrismApp.Shell, PrismApp"/>
    </container>
  </unity>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
</configuration>

In Bootstrapper class, I have following code:

public class PrismAppBootstrapper : UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        var obj =  ServiceLocator.Current.GetInstance<IShell>() as DependencyObject;
        return obj;
    }
}

In the WPF application's App.xaml.cs, I am instantiating PrismAppBootstrapper:

 PrismAppBootstrapper prismAppBootstrapper = new PrismAppBootstrapper();
        prismAppBootstrapper.Run();

However, when I run this code, I get the Exception : "InvalidOperationException - The current type, Interfaces.IShell, is an interface and cannot be constructed. Are you missing a type mapping?"

How to solve this problem? Why does application fail to know the registered type of IShell which is there in app.config file?

2

There are 2 answers

0
Learner On BEST ANSWER

Keeping the Shell configurable is possible with the Unity container.

The problem was that my Unity Container was not properly configured to read mapping/registrations from the app.config file. So it failed to know the mapping of IShell at run time.

I had to override other methods along with CreateShell in my PrismAppBootstrapper class.

E.g.

public class PrismAppBootstrapper : UnityBootstrapper
    {
        protected override IModuleCatalog CreateModuleCatalog()
        {
            ModuleCatalog catalog = new ConfigurationModuleCatalog();
            return catalog;
        }

        protected override void ConfigureContainer()
        {
            base.ConfigureContainer();
            UnityConfigurationSection configurationSection =
                (UnityConfigurationSection) ConfigurationManager.GetSection("unity");
            if (configurationSection != null)
            {
                configurationSection.Configure(this.Container);
            }
        }

        protected override DependencyObject CreateShell()
        {
            IShell shell = this.Container.TryResolve<IShell>();
            return shell as Window;
        }

        protected override void InitializeShell()
        {
            base.InitializeShell();

            Application.Current.MainWindow = (Window)this.Shell;
            Application.Current.MainWindow.Show();
        }
    }
2
Espen Medbø On

Shouldnt you instead use the UnityBootstrapper's Container to resolve your shell?

var obj =  Container.Resolve<IShell>() as DependencyObject;
return obj;