Real-world sample code for Factory Method Design Pattern with Dependency Injection using Autofac in ASP.NET MVC

Gang of Four (GOF) Design Patterns (23 Design Patterns in total) is categorized in three groups:  Creational, Structural, and Behavioral. Factory Method Design Pattern lies under Creational Patterns. Factory Method Design Pattern encapsulate the implementation details of creating objects, which inherits a common base class or which implements a common interface. Factory Method Design Pattern is one of the highly used design pattern.

Autofac is an Inversion of Control (IOC) container for .NET which is used in the below sample code.

Below sample code show how to implement Factory Method Design Pattern with Dependency Injection (DI) using Autofac.

 

Step 1:  Setup Autofac (Inversion of Control container)

Install Autofac.Mvc5 Nuget package. Add Bootstrapper.cs class in App_Start directory:

using System.Reflection;
using System.Web.Mvc;
using Autofac;
using Autofac.Integration.Mvc;
using System;

namespace SampleApplication
{
    /// <summary>
    ///     Bootstrapper class.
    /// </summary>
    public static class Bootstrapper
    {
        public static void Run()
        {
            SetAutofacContainer();
        }

        private static void SetAutofacContainer()
        {
            var builder = new ContainerBuilder();
            builder.RegisterControllers(Assembly.GetExecutingAssembly());
            builder.RegisterSource(new ViewRegistrationSource());
            builder.RegisterFilterProvider();
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }
    }
}

Update Global.asax class to call Run method of Bootstrapper class as shown below:

using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace SampleApplication
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            Bootstrapper.Run();
        }
    }
}

Step 2: Add classes participating in Factory Method Design Pattern:

Add the XmlType enum, IProcessXml interface, ProcessType1Xml  class, ProcessType2Xml  class & ProcessType3Xml  class as shown below.

Note here ProcessType1Xml , ProcessType2Xml & ProcessType3Xml  classes implement the common  IProcessXml interface.

namespace SampleApplication.ProcessUtility
{
    /// <summary>
    ///     Xml type.
    /// </summary>
    public enum XmlType
    {
        Type1,
        Type2,
        Type3,
    }

    /// <summary>
    ///     ProcessXml interface.
    /// </summary>
    public interface IProcessXml
    {
        /// <summary>
        ///     Process xml data.
        /// </summary>
        /// <param name="xmlString">Xml Data as string.</param>
        void ProcessXmlData(string xmlString);
    }

    /// <summary>
    ///     ProcessType1Xml class.
    /// </summary>
    public class ProcessType1Xml : IProcessXml
    {
        /// <summary>
        ///     Process xml data.
        /// </summary>
        /// <param name="xmlString">Xml Data as string.</param>
        public void ProcessXmlData(string xmlString)
        {
            // Type1 xml data processing code.
        }
    }

    /// <summary>
    ///     ProcessType2Xml class.
    /// </summary>
    public class ProcessType2Xml : IProcessXml
    {
        /// <summary>
        ///     Process xml data.
        /// </summary>
        /// <param name="xmlString">Xml Data as string.</param>
        public void ProcessXmlData(string xmlString)
        {
            // Type2 xml data processing code.
        }
    }

    /// <summary>
    ///     ProcessType3Xml class.
    /// </summary>
    public class ProcessType3Xml : IProcessXml
    {
        /// <summary>
        ///     Process xml data.
        /// </summary>
        /// <param name="xmlString">Xml Data as string.</param>
        public void ProcessXmlData(string xmlString)
        {
            // Type3 xml data processing code.
        }
    }
}

Step 3: Set Factory Method using Dependency Injection

Update the SetAutofacContainer() method of Bootstrapper class to set Factory Method using Dependency Injection as shown below:

private static void SetAutofacContainer()
{
	var builder = new ContainerBuilder();
	builder.RegisterControllers(Assembly.GetExecutingAssembly());

	builder.Register<Func<XmlType, IProcessXml>>(c =>
	{
		return (type) =>
		{
			switch (type)
			{
				case XmlType.Type1:
					{
						return new ProcessType1Xml();
					}

				case XmlType.Type2:
					{
						return new ProcessType2Xml();
					}

				case XmlType.Type3:
					{
						return new ProcessType3Xml();
					}

				default:
					{
						return new ProcessType1Xml();
					}
			}
		};
	});

	builder.RegisterSource(new ViewRegistrationSource());
	builder.RegisterFilterProvider();
	var container = builder.Build();
	DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

Step 4: Add ProcessData ActionMethod in HomeController  class that processes xml string based of the XmlType enum.

Add HomeController  controller in which, we have injected Func<XmlType, IProcessXml> processXmlFunction (process xml function delegate) using constructor injection. Also, add ProcessData ActionMethod that processes xml string based of the XmlType.

Func<XmlType, IProcessXml> processXmlFunction: encapsulates a method that has one parameter of XmlType type  and returns a value of the type IProcessXml.

using SampleApplication.ProcessUtility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace SampleApplication.Controllers
{
    public class HomeController : Controller
    {
        /// <summary>
        ///   Process xml function delegate.
        /// </summary>
        private readonly Func<XmlType, IProcessXml> _processXmlFunction;

        /// <summary>
        ///     Home controller constructor.
        /// </summary>
        /// <param name="processXmlFunction">Process xml function delegate.</param>
        public HomeController(Func<XmlType, IProcessXml> processXmlFunction)
        {
            _processXmlFunction = processXmlFunction;
        }

        /// <summary>
        ///     Process Xml Data and return result.
        /// </summary>
        /// <param name="type">Xml Type.</param>
        /// <param name="xmlString">Xml Data as string.</param>
        /// <returns>View.</returns>
        [HttpPost]
        public virtual ActionResult ProcessData(XmlType type, string xmlString)
        {
            var processXml = _processXmlFunction(type);
            processXml.ProcessXmlData(xmlString);

            return View();
        }
    }
}

 

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *