谈到IoC和ASP.NET的集成,很多人会先后想到Ninject,不过我们个人还是倾向于Unity。这篇文章简单地介绍如果创建基于Unity的ControllerFactory。如下面的代码所示,我们通过直接继承DefaultControllerFactory创建一个自定的UnityControllerFactory。构造函数指定的是配置的UnityContainer的名称,如果没有显式指定则采用默认的UnityContainer。在重写的GetControllerInstance方法中,直接调用IUnityContainer的Resolve方法根据Controller类型创建相应的对象。[源代码从这里下载] 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: } 为了演示DefaultControllerFactory的作用,我们来创建一个简单的例子。假设我们要创建一个维护联系人的应用,我们通过具有如下定义的Contact类型表示联系人,而IContactRepository接口定义了一个从存储中获取所有联系人的GetAllContacts方法,DefaultContactRepository是对IContactRepository接口的实现。 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: } 我们在Web应用的主页显示联系人列表,为此我创建了如下一个HomeController。在这里我们演示的是构造器注入,所以我们通过构造函数指定的IContactRepository对象来初始化Repository属性。在Action方法Index中调用IContactRepository的GetAllContacts方法为对应的View指定Model。 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: } Index.cshtml代码如下所示,这是一个Model类型为IEnumerable<Contact>的View,它将所有的联系人信息列出来。 1: @model IEnumerable<Artech.Web.Mvc.Extensions.Contact> 2: @{ 3: ViewBag.Title = "Index"; 4: } 5: 6: <h2>Contact List</h2> 7: 8: <div> 9: <ul> 10: @foreach (var contact in this.Model) 11: { 12: <li> 13: <h3>@contact.Name</h3> 14: <p>Gender: @contact.Gender</p> 15: <p>Address: @contact.Address</p> 16: <hr /> 17: </li> 18: } 19: </ul> 20: </div> 自定义的UnityContainerFactory的注册定义在Gloable.asax中。初次之外,额外需要做的是忽略掉针对favicon.ico的路由,否则程序运行将会失败。 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: } 接口IContactRepository和DefualtContactRepository之间的映射关系定义在如下所示的<unity>配置中。 1: <unity> 2: <alias alias="IContactRepository" type="Artech.Web.Mvc.Extensions.IContactRepository, UnityIntegration" /> 3: <alias alias="DefaultContactRepository" type="Artech.Web.Mvc.Extensions.DefaultContactRepository, UnityIntegration" /> 4: <container> 5: <register type="IContactRepository" mapTo="DefaultContactRepository"/> 6: </container> 7: </unity> 通过浏览器访问Web应用的主页,将会得到如下所示的联系人列表。 |
|