Showing posts with label Modularity. Show all posts
Showing posts with label Modularity. Show all posts

Tuesday, October 22, 2013

Catel extends Prism modularity options through NuGet

Introduction


Prism provides a lot of options regarding modularity by default. Fact is that most of the stuff  you need to build a modularized application is available on Prism. Prism contains several modularity options including ways to retrieve modules from a directory, set them up through the configuration file, and even options to create modularized Silverlight applications.

On the other hand, Catel provides support for module catalog composition in order to enable more than one modularity options into a single application.

Nowadays, initiatives around NuGet come from everywhere, such as Shimmer with the same goal of ClickOnce (but works), OctopusDeploy for release promotion and application deployment or even the recently released extension manager of ReSharper 8.0.

So, the Catel team comes with a new one and the fact is that we wondered why no one told about this before: 

What if you would be able to distribute your application's modules through NuGet?

If you want to know how, take a look.


Enabling NuGet based modularity option


With the forthcoming 3.8 version of Catel you will be able to install and load modules from a NuGet repository. The only thing you have to do is:
  1. Write a module as you know with Prism (or better in combination with Catel).
  2. Create a NuGet package for the module and publish it into your favorite gallery.
  3. Use and configure the NuGetBasedModuleCatalog in the application’s bootstrapper.
The first two steps are well documented. For details see creating and publishing a package and declaring modules from NuGet and Catel documentation.


So, now we can focus on the third one.

Use and configure the NuGetBasedModuleCatalog in the application’s bootstrapper


In order to simplify the following explanation we published a package into the official NuGet Gallery named Catel.Examples.WPF.Prism.Modules.NuGetBasedModuleA. Such package contains an assembly with a single class like this one:
 
public class NuGetBasedModuleA : ModuleBase
{
    public NuGetBasedModuleA(IServiceLocator container):base("NuGetBasedModuleA", null, container)
    {
    }

    protected virtual void OnInitialized()
    {
      var messageService = this.Container.ResolveType<IMessageService>();
      messageService.Show("NuGetBasedModuleA Loaded!!");
    }
}

Let’s start writing an  application that will use this public packaged module. Indeed, the main point of interest here is about the usage and configuration of the NuGetBasedModuleCatalog. Therefore just write the bootstrapper as follow:

public class Boot : BootstrapperBase<MainWindow, NuGetBaseModuleCatalog>
{
  protected override void ConfigureModuleCatalog()
  {
    base.ConfigureModuleCatalog();
    this.ModuleCatalog.AddModule(new ModuleInfo 
          { 
               ModuleName = "NuGetBasedModuleA", 
               ModuleType = "Catel.Examples.WPF.Prism.Modules.NuGetBasedModuleA.NuGetBasedModuleA, Catel.Examples.WPF.Prism.Modules.NuGetBasedModuleA", 
               Ref = "Catel.Examples.WPF.Prism.Modules.NuGetBasedModuleA, 1.0.0-BETA", 
               InitializationMode = InitializationMode.OnDemand
          });
  }
}

Notice how the Ref property of ModuleInfo is used to specify the package id and optionally the version number. If the version number is not specified then the application always will try to download the latest version keeping the modules up to date.

Finally, to make this demo work, just put in the XAML of the main window the ModuleManagerView control, run


and click the check box.

Conclusions


Yes, we did it again. Catel keeps working alongside Prism. Now, we extended Prism’s modularity options through NuGet in order to provide a powerful mechanism of application module distribution. 

If you want to try, just get the latest beta package of Catel.Extensions.Prism and discover by yourself all scenarios that you can handle with this Catel exclusive feature.

Friday, November 2, 2012

More about Catel and Prism in combination

Introduction

Since Catel 3.2 the support of Prism was enhanced. The fact is that several classes were introduced into Catel.Extensions.Prism to simplify the modules and bootstrapper implementation, and thanks to dependency injection support of the ServiceLocator everything can be done with Catel without the usage of third party containers.

But  now, with 3.4, a lot of improvements were introduced and the Prism extension is working like charm.

Lets take a look to a couple of scenarios.
 

Modularity with Catel explained

Probably you actually noticed the close resemblance of the UI with the Prism's Quick Start examples (with MEF or Unity). Actually this example is an adaptation of the original sources in order to show how use the Prism features in combination with Catel.

   

Here are some implementation details:

1) Catel comes with two versions of  generic classes, named BootstrapperBase, that helps to initialize with ease the shell and the module catalog. There are several methods that you are able to override, such as ConfigureContainer or ConfigureModuleCatalog, in order to setup the IoC container (a.k.a ServiceLocator) and the module catalog respectively, just like this:

    /// <summary>
    /// Initializes Prism to start this quickstart Prism application to use Catel.
    /// </summary>
    public class QuickStartBootstrapper : BootstrapperBase<Shell, CompositeModuleCatalog>
    {
        #region Fields

        /// <summary>
        /// The callback logger.
        /// </summary>
        private readonly CallbackLogger callbackLogger = new CallbackLogger();

        #endregion

        #region Methods

        /// <summary>
        /// Configures the <see cref="IServiceLocator"/>. May be overwritten in a derived class to add specific
        /// type mappings required by the application.
        /// </summary>
        protected override void ConfigureContainer()
        {
            base.ConfigureContainer();
            Container.RegisterTypeIfNotYetRegistered<IModuleTracker, ModuleTracker>();

            LogManager.AddListener(callbackLogger);

            Container.RegisterInstance<CallbackLogger>(callbackLogger);
        }

        /// <summary>
        /// Configures the <see cref="IModuleCatalog"/> used by Prism.
        /// </summary>
        protected override void ConfigureModuleCatalog()
        {
            ModuleCatalog.Add(Catel.Modules.ModuleCatalog.CreateFromXaml(new Uri("/ModularityWithCatel.Silverlight;component/ModulesCatalog.xaml", UriKind.Relative)));

            var moduleCatalog = new ModuleCatalog();
            // Module A is defined in the code.
            Type moduleAType = typeof(ModuleA.ModuleA);
            moduleCatalog.AddModule(new ModuleInfo(moduleAType.Name, moduleAType.AssemblyQualifiedName, "ModuleD"));

            // Module C is defined in the code.
            Type moduleCType = typeof(ModuleC.ModuleC);
            moduleCatalog.AddModule(new ModuleInfo { ModuleName = moduleCType.Name, ModuleType = moduleCType.AssemblyQualifiedName, InitializationMode = InitializationMode.OnDemand });

            ModuleCatalog.Add(moduleCatalog);
        }

        #endregion
    }

2) Catel also comes with the CompositeModuleCatalog class to deal with many catalog as one. The current implementation actually "allow" cross module catalog's module dependencies.

3) For a module implementation the common approach is  inherit from ModuleBase just like this:


    /// <summary>
    /// A module for the quickstart.
    /// </summary>
    public class ModuleA : ModuleBase
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ModuleA"/> class.
        /// </summary>
        /// </param name="moduleTracker">The module tracker.</param>        
        public ModuleA(IModuleTracker moduleTracker) : base("ModuleA", moduleTracker)
        {
        }
    }

4) The common implementation of the application class is about the instantiation of the Bootstrapper and making a call to the Run method.

var bootstrapper = new QuickStartBootstrapper();
bootstrapper.Run();

But, what will happend if you call RunWithSplashScreen instead? Try with the latest beta and discover the feature by your self or just take a look into orchesta.

Enhanced working with regions

Some time ago, I wrote about a feature where your were able to inject a view from a view model from it's view model:
 
 
	var employeeViewModel = new EmployeeViewModel();
	var uiVisualizerService = GetService<IUIVisualizerService>();
	uiVisualizerService.Activate(viewModel, "MainRegion");

1) But now you can deal with more than one shell and do this:

	uiVisualizerService.Activate(employeeViewModel, this, "MainRegion");

Where the second parameter is the parent view-model.

2) Actually you are able to inject views (referencing it's view models) in any window. Just like the previous example but in combination with the experimental extension method Show:

	var uiVisualizerService = GetService<IUIVisualizerService>();
	var windowViewModel = new WindowWithRegionViewModel();
	uiVisualizerService.Show(windowViewModel, () => { uiVisualizerService.Activate(new EmployeeViewModel(),  windowViewModel, "WindowMainRegion") });

Conclusions

1) The usage of third party Prism Extensions like MEF or Unity is no longer required. Catel Service Locator support dependency injection and is actually configured to work just as Prism expect, the fact is that the ServiceLocatorAdapter do this job.
 
2) Now, you are able to have a nice programming session with Prism & Catel.

X-ray StoneAssemblies.MassAuth with NDepend

Introduction A long time ago, I wrote this post  Why should you start using NDepend?  which I consider as the best post I have ever...