How-To Use S#arp Architecture and S#arp Architecture Contrib in Windows GUI and Service Applications

The S#arp Architecture Contrib team believes that most developers using S#arp Architecture in non-web applications want to leverage work already done in a web application. For example, you might need a web service to run background processing tasks for your web application. Therefore, this how-to focuses on adding a Windows application to an existing solution that already has a working web. If you don't have a working web yet, you can use the solution template that comes with S#arp Architecture to create one.

Note that you no longer need to use PostSharp with Contrib as it now uses Castle Interceptors

Edit

Setup

Your project must configure NHibernate and Castle Windsor at startup.

Step 1: NHibernate Configuration File

Add a link to your web's NHibernate.config to your Windows application. If you are unsure how to do this, check out the information on adding an item as a link in this Microsoft article How to: Add Existing Items to a Project.

Step 2: Move <Your Project>.Web.CastleWindsor.ComponentRegistrar to a Shared DLL

<Your Project>.Web.CastleWindsor.ComponentRegistrar will need to be accessed by your Windows application. Of course, you cannot reference your web DLL from your Windows application so it will have to be moved to a common location. Arguably, this is an application service and can be moved to <Your Project>.ApplicationServices.CastleWindsor.

Step 3: Create a Static Class to Initialize Service Locator

Add the following class to <Your Project>.ApplicationServices.CastleWindsor:

using Castle.Windsor;
using CommonServiceLocator.WindsorAdapter;
using Microsoft.Practices.ServiceLocation;

namespace <Your Project>.ApplicationServices.CastleWindsor {
    public static class ServiceLocatorInitializer {
        public static void Init() {
            IWindsorContainer container = new WindsorContainer();
            //Register all the Contrib Components
            SharpArchContrib.Castle.CastleWindsor.ComponentRegistrar.AddComponentsTo(container);
            ComponentRegistrar.AddComponentsTo(container);
            ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(container));
        }
    }
}

Step 4: Create a Static Class to Initialize NHibernate

Add the following class to <Your Project>.Data:

using <Your Project>.Data.NHibernateMaps;
using SharpArch.Data.NHibernate;
using SharpArchContrib.Data.NHibernate;

namespace <Your Project>.Data {
    public static class Initializer {
        public static void Init() {
            NHibernateSession.Init(new ThreadSessionStorage(),
                                   new[] {"<Your Project>.Data.dll"},
                                   new AutoPersistenceModelGenerator().Generate(),
                                   "NHibernate.config");
        }
    }
}

Notice that this configuration is using ThreadSessionStorage, which is required if you will be using the UnitOfWork support. If you are using the Transaction attribute you can still use WebSessionStorage.

Step 5: Initialize Service Location and NHibernate When Application Starts

Make sure to call <Your Project>.ApplicationServices.CastleWindsor.ServiceLocatorInitializer.Init() followed by <Your Project>.Data.Initializer() when your application starts.

Important!: Make sure you register the components from SharpArchContrib before registering any components from your project. Failing to do this will result in castle not recognizing the Transaction or UnitOfWork attributes since the interceptor has not been registered yet.

Edit

Session Management

For best results you should attribute any method that performs NHibernate operations with the UnitOfWork attribute. The UnitOfWork attribute will ensure that your application adheres to best-practices when using NHibernate. Review the documentation on UnitOfWork for more information.