Up Development guide

Bootstrapping

Last modified on August 15, 2012 17:21

Cocktail is not one monolithic framework, but rather lots of little pieces of functionality that are composed together when the application starts up. Configuration of this composition, including customizing any of the pieces, is done via the bootstrapper.


Creating a bootstrapper

A bootstrapper in Cocktail is created by extending the generic class FrameworkBootstrapper<TRootModel>

The bootstrapper requires the type of the root ViewModel, so it can instantiate and activate it once the configuration steps have finished. The root ViewModel must be annotated with the proper MEF export attribute in order for the bootstrapper to create an instance through MEF.

C#
public class AppBootstrapper : FrameworkBootstrapper<ShellViewModel>
{
   // Add additional logic if required.
}

Lastly for the bootstrapper to come to live, it must be added as a static resource to your application's App.xaml.

Note: In WPF, the static resource must be contained in a ResourceDictionary.

Silverlight:

XAML
<Application x:Class="TempHire.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:TempHire">
    <Application.Resources>
        <local:AppBootstrapper x:Key="AppBootstrapper" />
    </Application.Resources>
</Application>

WPF:

XAML
<Application x:Class="TempHire.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:TempHire">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <local:AppBootstrapper x:Key="AppBootstrapper" />
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Runtime configuration

The StartRuntime method of the FrameworkBootstrapper provides the means to perform synchronous application configuration during startup of the application. This is the place where you as an application developer can put your own configuration logic. 

The following code shows an example of such a configuration. It initializes the DevForce Fake Backing Store in a WPF application during startup.

C#
public class AppBootstrapper : FrameworkBootstrapper<ShellViewModel>
{
    [Import]
   public IEntityManagerProvider<TempHireEntities> EntityManagerProvider;

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

        EntityManagerProvider.InitializeFakeBackingStore();
    }
}

DesignTime configuration

Whenever you open a XAML file in the Visual Studio Designer or Blend, the application starts in design-mode. At design time, the Cocktail bootstrapper skips all the runtime configuration, because at design time there are only certain things that can be done. For example you cannot connect to a server and fetch data while your application is executing inside the Visual Studio Designer or Blend. 

Occasionally the need arises to perform some configuration steps specifically for when the application runs in design-mode. The StartDesignTime method provides the means to perform this configuration.

C#
public class AppBootstrapper : FrameworkBootstrapper<ShellViewModel>
{
   protected override void StartDesignTime()
    {
       base.StartDesignTime();

       // Additional configuration only executed at design time.
   }
}

Asynchronous configuration

Certain configuration steps can only be executed asynchronously. In particular in Silverlight, where all server communication must be asynchronous. The FrameworkBootstrapper allows for such asynchronous configuration. The bootstrapper automatically waits for the asynchronous configuration to complete before continuing the application startup sequence. 

The StartRuntimeAsync method provides the means to perform asynchronous configuration. StartRuntimeAsync is a Coroutine that can perform one or more asynchronous operations.

Note that asynchronous configuration is only possible at runtime. There's no equivalent for asynchronous configuration at design time.

Examples for asynchronous configuration steps are eager loading certain XAP files, initializing the DevForce Fake Backing Store in Silverlight as opposed to WPF, where that same task can be performed synchronously, etc.

The following code demonstrates how to initialize the DevForce Fake Backing Store in Silverlight during startup.

C#
public class AppBootstrapper : FrameworkBootstrapper<ShellViewModel>
{
    [Import]
   public IEntityManagerProvider<TempHireEntities> EntityManagerProvider;

   protected override IEnumerable<IResult> StartRuntimeAsync()
    {
       yield return EntityManagerProvider.InitializeFakeBackingStoreAsync();
    }
}

Customizing the MEF catalog

Cocktail uses MEF as the Inversion-of-Control container. The FrameworkBootstrapper configures the container with a default parts catalog that is obtained from DevForce. This catalog contains all assemblies that were discovered during DevForce's Discovery phase.

The PrepareCompositionCatalog method allows for the developer to add to the default catalog or completely replace it with their own.

The following example demonstrates how to wrap the default catalog in an InterceptingCatalog available from MefContrib, for the purpose of centrally subscribing new instances to the EventAggregator.

C#
public class AppBootstrapper : FrameworkBootstrapper<ShellViewModel>, IExportedValueInterceptor
{
   object IExportedValueInterceptor.Intercept(object value)
    {
        SubscribeToEventAggregator(value);
       return value;
    }

   protected override void BuildUp(object instance)
    {
       base.BuildUp(instance);
        SubscribeToEventAggregator(instance);
    }

   // Use InterceptingCatalog from MefContrib to centrally handle EventAggregator subscriptions.
   protected override ComposablePartCatalog PrepareCompositionCatalog()
    {
        var cfg = new InterceptionConfiguration().AddInterceptor(this);
       return new InterceptingCatalog(Composition.Catalog, cfg);
    }

   private void SubscribeToEventAggregator(object instance)
    {
       if (instance is IHandle)
        {
            LogFns.DebugWriteLine(string.Format("Automatically subscribing instance of {0} to EventAggregator.",
                                                instance.GetType().Name));
            EventFns.Subscribe(instance);
        }
    }
}

Customizing the MEF CompositionContainer

The FrameworkBootstrapper automatically sets up an application scoped MEF container properly configured to work out of the box. It initializes the container with the default parts catalog obtained from DevForce or the custom catalog provided through the above PrepareCompositionCatalog method. In addition, it ensures that the container gets populated with the default EventAggregator, WindowManager and DialogManager

Replacing the default EventAggregator, WindowManager or DialogManager

The FrameworkBootstrapper always ensures that the container contains an EventAggregator, WindowManager and DialogManager. The EventAggregator provides a publish/subscribe service to loosely communicate between different components within the application. The WindowManager is responsible for displaying new windows and popups and the Cocktail DialogManager provides a convenient way to handle user prompts and messages.

As the application developer you may choose to replace the default implementation of any or all of these services. To replace any of these services, simply provide your own implementation and ensure that it will get discovered by annotating it with an ExportAttribute.

The following example demonstrates how to replace the EventAggregator with your own implementation.

C#
[Export(typeof(IEventAggregator))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class MyEventAggregator : IEventAggregator
{
   public void Subscribe(object instance)
    {
       // Custom implementation
   }

   public void Unsubscribe(object instance)
    {
       // Custom implementation
   }

   public void Publish(object message)
    {
       // Custom implementation
   }

   public void Publish(object message, Action<Action> marshal)
    {
       // Custom implementation
   }

   public Action<Action> PublicationThreadMarshaller { get; set; }
}

Adding additional objects to the container

On top of replacing any of the default services by implementing and exporting your own, the PrepareCompositionContainer method allows for the developer to manually add additional objects to the container through the provided CompositionBatch

The following example demonstrates how to add the Cocktail AuthenticationService to the container.

C#
public class AppBootstrapper : FrameworkBootstrapper<ShellViewModel>
{
   protected override void PrepareCompositionContainer(CompositionBatch batch)
    {
       base.PrepareCompositionContainer(batch);

        batch.AddExportedValue<IAuthenticationService>(new AuthenticationService());
    }
}
Tags: Cocktail
Created by DevForce on January 23, 2012 18:16

This wiki is licensed under a Creative Commons 2.0 license. XWiki Enterprise 3.2 - Documentation. Copyright © 2015 IdeaBlade