My project setup, Part 1 - Initialization

by Jakobsson 4. March 2010 19:14

A while ago I wrote a post about what tools and frameworks I use in my web applications. Now I thought I'd write a small series about how I use those tool. In this first part I'll write about the initial setup and how I use my ioc container.

A lot in my applications revolve around my ioc container. I try to make it take the heavy lifts to make my coding easier. I have created a base bootstrapper that doesn't depend on a specific container. That class looks like this:



    public abstract class BootstrapperBase : IBootstrapper
    {
        private readonly List<Assembly> assemblies = new List<Assembly>();

        protected BootstrapperBase(IEnumerable<Assembly> assemblies)
        {
            this.assemblies.AddRange(assemblies);
        }

        public virtual void Execute()
        {
            ExecuteCore();
            SetServiceLocator();
            ServiceLocator.Current.GetAllInstances<IInitializationTask>()
                          .ForEach(x => x.Execute());
        }

        protected IEnumerable<Type> GetAllTypesInAssemblies<T>()
        {
            return
                GetAssemblies().SelectMany(
                    x => x.GetTypes().Where(y => typeof(T).IsAssignableFrom(y) && typeof(T) != y));
        }

        protected abstract void ExecuteCore();
        protected abstract void SetServiceLocator();

        protected virtual IEnumerable<Assembly> GetAssemblies()
        {
            return assemblies.Distinct();
        }
    }


It's quite simple. It takes a list of all assemblies that should be searched when I initialize my ioc container. Then it has a Execute() method (from the IBootstrapper interface). This basicly calls the ExecuteCore() abstract method that will initialize the container. Then it calls the SetServiceLocator() abstract method that will set a servicelocator for the ioc I'm using. Then it uses the servicelocator to get all instances of IInitializationTask and call the execute method on them.

The IInitializationTask interface looks like this:



public interface IInitializationTask
{
    void Execute();
}



Very simple with just one method, Execute(), that will execute the task. Everything that I want to initialize at the start of the application implements this interface. This could be registering my routes, setting up automapper or anything else that you want to execute on application startup.

Now I need a implementation of my base bootstrapper for the ioc container I want to use. My favorite is structuremap. And here is my bootstrapper for structuremap:



public class StructureMapBootstrapper : BootstrapperBase
    {
        public StructureMapBootstrapper(IEnumerable<Assembly> assemblies)
            : base(assemblies)
        {

        }

        protected override void ExecuteCore()
        {
            ObjectFactory.Initialize(x =>
            {
                GetRegistries().ForEach(x.AddRegistry);

                x.Scan(y =>
                {
                    y.WithDefaultConventions();

                    GetAssemblies().ForEach(y.Assembly);

                    y.AddAllTypesOf(typeof(IInitializationTask));
                    y.AddAllTypesOf(typeof(IConsumer<>));
                });
            });
        }

        protected override void SetServiceLocator()
        {
            ServiceLocator.SetLocatorProvider(() => new StructureMapServiceLocator());
        }

        protected virtual IEnumerable<Registry> GetRegistries()
        {
            var types = GetAllTypesInAssemblies<Registry>();
            return types.Select(x => (Registry)Activator.CreateInstance(x));
        }
    }



The interesting part here is the ExecuteCore() method. It initializes structuremap and first it adds all the implementations of the structuremap Registry class that it can find in the assemblies of the application. Then it scans all applications and adds all classes that implements the interface IInitializationTask (that I described earlier). Then it adds all classes that implements the IConsumer<> interface. I use the IConsumer<> to subscribe to events that I can publish from my application. You can read how that is done in this post.

Now i just need a way of calling my bootstrapper in my application. For this I have first created a MvcApplicationBase class. This is a class that inherits from the HttpApplication class. It looks like this:



public abstract class MvcApplicationBase : HttpApplication
{
    private IBootstrapper bootstrapper;

    public IBootstrapper Bootstrapper
    {
        get
        {
            return bootstrapper ?? (bootstrapper = CreateBootstrapper());
        }
    }

    public void Application_Start()
    {
        Bootstrapper.Execute();
        OnStart();
    }

    public void Application_End()
    {
        OnEnd();
    }

    protected abstract IBootstrapper CreateBootstrapper();

    protected virtual void OnStart()
    {
    }

    protected virtual void OnEnd()
    {
    }
}



This is pretty simple. It has a abstract method, GetBootstrapper(), that I call to get the bootstrapper and executes it in the Application_Start() method.

Then I need a implementation of this class for my structuremap. This class looks like this:



public abstract class StructureMapMvcApplication : MvcApplicationBase
{
    protected StructureMapMvcApplication()
    {
        BeginRequest += delegate
                            {
                                ServiceLocator.Current.GetInstance<IEventPublisher>().Publish(new BeginRequest(this));
                            };
        EndRequest += delegate
                          {
                              ServiceLocator.Current.GetInstance<IEventPublisher>().Publish(new EndRequest(this));
                          };
    }

    protected abstract IEnumerable<Assembly> GetAssemblies();

    protected override IBootstrapper CreateBootstrapper()
    {
        return new StructureMapBootstrapper(GetAssemblies());
    }
}



Here I publish two events when a request begins and when a request ends (explained in the link I gave earlier). Then I override the GetBootstrapper() method and creates a instance of my StructuremapBootstrapper. I also have a abstract method, GetAssemblies(), that will return all assemblies I want to search when I initialize structuremap.

All the code from this post sits in a base assembly that I use for just about all my applications. It contains the basic generic stuff that I want to do in just about every web application. In my next post I will show you how this fits into the application and how I extend it with the application-specific initialization and how I set up nhibernate in my applications. Stay tuned.

Tags:
Categories: C#

Comments

trackback
DotNetShoutout on 3/4/2010 9:23:54 PM

CodeJunkies | My project setup, Part 1 - Initialization

Thank you for submitting this cool story - Trackback from DotNetShoutout

trackback
iAwaaz-News-for-the-People-by-the-People on 3/6/2010 2:23:55 AM

CodeJunkies | My project setup, Part 1 - Initialization

Thank you for submitting this cool story - Trackback from iAwaaz-News-for-the-People-by-the-People

trackback
9eFish on 3/7/2010 3:45:57 AM

CodeJunkies | My project setup, Part 1 - Initialization

9efish.感谢你的文章 - Trackback from 9eFish

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading