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(); } } }
.NET Professional | Microsoft Certified Professional | DZone’s Most Valuable Blogger | Web Developer | Author | Blogger
Doctorate in Computer Science and Engineering
Microsoft Certified Professional (MCP) with over 12+ years of software industry experience including development, implementation & deployment of applications in the .NET framework
Experienced and skilled Agile Developer with a strong record of excellent teamwork, successful coding & project management. Specialises in problem identification and proposal of alternative solutions. Provided knowledge and individual mentoring to team members as needed
Among top 3% overall in terms of contribution on Stack Overflow (~2.3 million people reached my posts). Part of the top 1% Stack Overflow answerers in ASP.NET technology.
DZone’s Most Valuable Blogger (MVB)
Created and actively maintain the TechCartNow.com tech blog while also editing, writing, and researching topics for publication.
Excellent skills in Application Development using C#/Vb.Net, .NET Framework, ASP.NET, MVC, ADO.NET, WCF, WPF, Web API, SQL Server, jQuery, Angular, React, BackboneJS
Hi, DO you know how to achieve this in .Net Core with same example. Please help.
Thank so much, it is very helpful to me