GlassMapper with Unity as DI Container

Default GlassMapper demo application uses CastleWindsor as DI container to resolve the dependencies in the runtime. This is also documented as part of the 1st tutorials on glass mapper site. There is another implementation with SimpleInjector but in situation if you are using Unity as DI Container in your application this will not work you need to either use unity with CastleWindsor or change the implementation. I did see a question related to Unity on the Glass Mapper google group forum.

Glass Mapper’s CastleWindsor DI implementation has 4 component.

  1. DependencyResolver
  2. GlassMapperSc
  3. GlassMapperScCustom
  4. IObjectConstruction Pipeline
  5. SitecoreInstaller

I used the same implementation and converted to work with Unity.

DependecyResolver

    public class DependencyResolver : IDependencyResolver
    {
        /// <summary> 
        /// Creates the standard resolver. 
        /// </summary> 
        /// IDependencyResolver. 
        public static DependencyResolver CreateStandardResolver()
        {
            Microsoft.Practices.Unity.IUnityContainer container = new Microsoft.Practices.Unity.UnityContainer();
            return new DependencyResolver(container);
        }

        /// <summary> 
        /// Initializes a new instance of the  class. 
        /// </summary> 
        /// The container. 
        public DependencyResolver(Microsoft.Practices.Unity.IUnityContainer container)
        {
            this.Container = container;
        }

        public Microsoft.Practices.Unity.IUnityContainer Container
        {
            get;
            private set;
        }

        public T Resolve<T>(IDictionary args = null)
        {
            return this.Container.Resolve<T>();
        }

        public IEnumerable<T> ResolveAll<T>()
        {
            return this.Container.ResolveAll<T>();
        }
    }

GlassMapperSc

[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(Setup.GlassMapper.GlassMapperSc), "Start")]

namespace Setup.GlassMapper
{
    public static class GlassMapperSc
    {
        public static void Start()
        {
            //create the resolver
            var resolver = DependencyResolver.CreateStandardResolver();

            //install the custom services
            GlassMapperScCustom.ContainerConfig(resolver.Container);

            //create a context
            var context = Glass.Mapper.Context.Create(resolver);
            context.Load(GlassMapperScCustom.GlassLoaders());

            GlassMapperScCustom.PostLoad();
        }
    }
}

GlassMapperScCustom

    public static class GlassMapperScCustom
    {
        public static void ContainerConfig(IUnityContainer container)
        {
            var config = new Config();

            container.Register<IObjectConstructionTask, UnityConstruction>();
            //  config.EnableCaching = false;

            container.Register(new SitecoreInstaller(config));
        }

        public static IConfigurationLoader[] GlassLoaders()
        {
            var attributes = new SitecoreAttributeConfigurationLoader("Sitecore.Models");
            return new IConfigurationLoader[] { attributes };
            //return new IConfigurationLoader[] { attributes, Models.Config.ContentConfig.Load() };
        }

        public static void PostLoad()
        {
            //Comment this code in to activate CodeFist
            /* CODE FIRST START
            var dbs = Sitecore.Configuration.Factory.GetDatabases();
            foreach (var db in dbs)
            {
                var provider = db.GetDataProviders().FirstOrDefault(x => x is GlassDataProvider) as GlassDataProvider;
                if (provider != null)
                {
                    using (new SecurityDisabler())
                    {
                        provider.Initialise(db);
                    }
                }
            }
             * CODE FIRST END
             */
        }
    }

IObjectConstruction pipeline

    public class UnityConstruction : IObjectConstructionTask
    {
        private static object _lock = new object();

        public void Execute(ObjectConstructionArgs args)
        {
            var resolver = args.Context.DependencyResolver as DependencyResolver;
            //check that no other task has created an object
            //also check that this is a dynamic object
            if (args.Result == null && !args.Configuration.Type.IsAssignableFrom(typeof(IDynamicMetaObjectProvider)))
            {
                //check to see if the type is registered with the container
                //if it isn't added it
                if (resolver.Container.IsRegistered(args.Configuration.Type))
                {
                    lock (_lock)
                    {
                        if (resolver.Container.IsRegistered(args.Configuration.Type))
                        {
                            resolver.Container.Register<object>(args.Configuration.Type);
                        }
                    }
                }

                //create instance using SimpleInjector
                var obj = resolver.Container.Resolve<object>(args.Configuration.Type);

                //map properties from item to model
                args.Configuration.MapPropertiesToObject(obj, args.Service, args.AbstractTypeCreationContext);

                //set the new object as the returned result
                args.Result = obj;
            }
        }
    }

Sitecore Installer
Sitecore installer class is really a big one and it uses IWindorInstaller implementation to partition the registration logic. As I am not aware that unity has any extension to support that, I created an extension to support it. As it is huge to copy the entire converted SitecoreIntaller code here, I am just giving the extension interface and method which I used to register the Sitecore Installer. Sitecore Installer and other installer classes will implement IUnityInstaller class and register the mapping of type with IUnityContainer object passed around.

    public interface IUnityInstaller
    {
        void Install(IUnityContainer container);
    }

    public static class UnityExtensions
    {
        public static void Register(this IUnityContainer container, IUnityInstaller installer)
        {
            installer.Install(container);
        }

        public static void Install(this IUnityContainer container, params IUnityInstaller[] installers)
        {
            foreach (var installer in installers)
                installer.Install(container);
        }
    }

I haven’t tested the complete code yet as I am still trying to build the framework piece before starting the actual development. In case if you have any issue drop me a note and I will look into it.

Advertisements

About cprakash

A developer, passionate about .Net, Architecture and Security.
This entry was posted in Sitecore and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s