When talking about the integration of IoC and ASP. NET, many people will think of Ninject first, but we personally prefer Unity. This article briefly introduces how to create a Unity-based ControllerFactory. The following code directly inherits DefaultControllerFactory to create a custom UnityControllerFactory. The constructor specifies the name of the configured UnityContainer. If it is not explicitly specified, the default UnityContainer is used. In the rewritten GetControllerInstance method, call the IUnityContainer Resolve method to create the corresponding object according to the Controller type. [Download the source code from here]
1: public class UnityControllerFactory: DefaultControllerFactory
2 :{
3: public IUnityContainer Container {get; private set ;}
4: public UnityControllerFactory (string containerName = "")
5 :{
6: IUnityContainer container = new UnityContainer ();
7: UnityConfigurationSection configSection = ConfigurationManager. GetSection (UnityConfigurationSection. SectionName) as UnityConfigurationSection;
8: if (null = configSection &&! String. IsNullOrEmpty (containerName ))
9 :{
10: throw new ConfigurationErrorsException ("Cannot find <unity> configuration section ");
11 :}
12:
13: if (string. IsNullOrEmpty (containerName ))
14 :{
15: configSection. Configure (container );
16 :}
17: else
18 :{
19: configSection. Configure (container, containerName );
20 :}
21: this. Container = container;
22 :}
23: protected override IController GetControllerInstance (RequestContext requestContext, Type controllerType)
24 :{
25: Guard. ArgumentNotNull (controllerType, "controllerType ");
26: return (IController) this. Container. Resolve (controllerType );
27 :}
28 :}
To demonstrate the role of DefaultControllerFactory, let's create a simple example. Suppose we want to create an application to maintain contacts. We use the Contact type defined below to represent contacts, And the IContactRepository interface defines a GetAllContacts method to retrieve all contacts from the storage, defaultContactRepository is the implementation of the IContactRepository interface.
1: public class Contact
2 :{
3: public string Name {get; set ;}
4: public string Gender {get; set ;}
5: public string Address {get; set ;}
6 :}
7:
8: public interface IContactRepository
9 :{
10: IEnumerable <Contact> GetAllContacts ();
11 :}
12:
13: public class DefaultContactRepository: IContactRepository
14 :{
15: public IEnumerable <Contact> GetAllContacts ()
16 :{
17: yield return new Contact
18 :{
19: Name = "Zhang San ",
20: Gender = "Male ",
21: Address = "#328, XingHu Street, Su Zhou, Jiang Su Province, PRC ."
22 :};
23:
24: yield return new Contact
25 :{
26: Name = "Li Si ",
27: Gender = "Female ",
28: Address = "#328, Jin Ji Hu Road, Su Zhou, Jiang Su Province, PRC ."
29 :};
30 :}
31 :}
The contact list is displayed on the homepage of the Web application. For this reason, a HomeController is created, as shown in the following figure. Here we demonstrate constructor injection, So we initialize the Repository attribute through the IContactRepository object specified by the constructor. Call the IContactRepository GetAllContacts method in the Action Method Index to specify a Model for the corresponding View.
1: public class HomeController: Controller
2 :{
3: public IContactRepository Repository {get; private set ;}
4: public HomeController (IContactRepository repository)
5 :{
6: this. Repository = repository;
7 :}
8: public ActionResult Index ()
9 :{
10: return View (this. Repository. GetAllContacts ());
11 :}
12 :}
The Index. cshtml code is as follows. This is a View of the Model type IEnumerable <Contact>, which lists all the Contact information.
1: @ model IEnumerable <Artech. Web. Mvc. Extensions. Contact>
2 :@{
3: ViewBag. Title = "Index ";
4 :}
5:
6:
7:
8: <div>
9: <ul>
10: @ foreach (var contact in this. Model)
11 :{
12: <li>
13:
14: <p> Gender: @ contact. Gender </p>
15: <p> Address: @ contact. Address </p>
16:
17: </li>
18 :}
19: </ul>
20: </div>
The registration of custom UnityContainerFactory is defined in Gloable. asax. For the first time, you need to ignore the route for favicon. ico. Otherwise, the program will fail to run.
1: public class MvcApplication: System. Web. HttpApplication
2 :{
3: public static void RegisterGlobalFilters (GlobalFilterCollection filters)
4 :{
5: filters. Add (new HandleErrorAttribute ());
6 :}
7:
8: public static void RegisterRoutes (RouteCollection routes)
9 :{
10: routes. IgnoreRoute ("favicon. ico ");
11: routes. IgnoreRoute ("{resource}. axd/{* pathInfo }");
12: routes. MapRoute ("Default", "{controller}/{action}/{id }",
13: new {controller = "Home", action = "Index", id = UrlParameter. Optional}
14 :);
15 :}
16:
17: protected void Application_Start ()
18 :{
19: AreaRegistration. RegisterAllAreas ();
20: RegisterGlobalFilters (GlobalFilters. Filters );
21: RegisterRoutes (RouteTable. Routes );
22:
23: ControllerBuilder. Current. SetControllerFactory (new UnityControllerFactory ());
24 :}
25 :}
The ing between IContactRepository and DefualtContactRepository is defined in the <unity> configuration as follows.
1: <unity>
2: <alias = "IContactRepository" type = "Artech. Web. Mvc. Extensions. IContactRepository, UnityIntegration"/>
3: <alias = "DefaultContactRepository" type = "Artech. Web. Mvc. Extensions. DefaultContactRepository, UnityIntegration"/>
4: <container>
5: <register type = "IContactRepository" mapTo = "DefaultContactRepository"/>
6: </container>
7: </unity>
Access the home page of the Web application through a browser. The following contact list is displayed.
Author: Artech